diff --git a/README.md b/README.md index 2d9d0c0f23..74a6df8ade 100644 --- a/README.md +++ b/README.md @@ -102,17 +102,21 @@ sidebars and page frontmatter, so they stay correct as content evolves. ## History: the GitBook import -The content in this repo was imported once from the obol-gitbook repo by a -migration script (`scripts/migrate-gitbook.mjs`) that converted -GitBook-flavoured markdown (hints, tabs, OpenAPI blocks, card tables, -figures, explicit heading anchors) to Docusaurus markdown/MDX, derived slugs -from the live site's `llms.txt`, generated sidebars from `SUMMARY.md`, and -normalized assets. The script has since been deleted — content is authored -here now, and re-running it would have overwritten local edits. If it is -ever needed again, recover it from git history: +All content in this repo (`next` + v1.10, and later v1.3–v1.9 from the +obol-gitbook `version-*` branches) was imported by a migration script that +converted GitBook-flavoured markdown (hints, tabs, OpenAPI blocks, card +tables, figures, explicit heading anchors) to Docusaurus markdown/MDX, +derived slugs from the live site's `llms.txt`, generated sidebars from +`SUMMARY.md`, and normalized assets. With every version migrated, the script +has been deleted; content is authored in this repo now, and each ported +version received manual link/anchor fixes after import that a re-run would +have clobbered. If it is ever needed again, recover it from git history: ```shell git log --diff-filter=D -- scripts/migrate-gitbook.mjs ``` -Its lasting output is the content itself plus `scripts/generated/redirects.json`. +Versions before v1.3 were removed in the 2026 rebuild. They remain available +in this repo's history — the last commit carrying them is +[`000db7c5b0`](https://github.com/ObolNetwork/obol-docs/tree/000db7c5b0/versioned_docs) +— and the version dropdown's "Legacy (pre-v1.3)" item points there. diff --git a/docusaurus.config.js b/docusaurus.config.js index 53df47860b..6f3fdcddb9 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -115,6 +115,12 @@ const config = { { fromExtensions: ['html', 'htm'], redirects: legacyRedirects, + // GitBook served old versions at /version-vX.Y/... — keep those URLs + // alive now that the same pages live at /vX.Y/... + createRedirects(existingPath) { + const m = existingPath.match(/^\/(v\d+\.\d+)\//); + return m ? [existingPath.replace(m[0], `/version-${m[1]}/`)] : []; + }, }, ], './plugins/llms-txt', @@ -261,6 +267,14 @@ const config = { { type: 'docsVersionDropdown', position: 'right', + dropdownItemsAfter: [ + { + // Pre-v1.3 docs were removed in the 2026 rebuild; they live in + // this repo's history at the last commit before the rebuild. + href: 'https://github.com/ObolNetwork/obol-docs/tree/000db7c5b0/versioned_docs', + label: 'Legacy (pre-v1.3)', + }, + ], }, { href: 'https://launchpad.obol.org', diff --git a/plugins/llms-txt/index.js b/plugins/llms-txt/index.js index 0ee07ff9f4..1070e982ba 100644 --- a/plugins/llms-txt/index.js +++ b/plugins/llms-txt/index.js @@ -91,9 +91,10 @@ module.exports = function llmsTxtPlugin(context) { const {siteDir} = context; // e.g. https://docs.obol.org or https://obolnetwork.github.io/obol-docs const siteUrl = `${siteConfig.url}${siteConfig.baseUrl.replace(/\/$/, '')}`; - const lastVersion = JSON.parse( + const allVersions = JSON.parse( fs.readFileSync(path.join(siteDir, 'versions.json'), 'utf8'), - )[0]; + ); + const lastVersion = allVersions[0]; const versions = [ {name: 'next', heading: 'Next', base: '/next'}, { @@ -102,6 +103,11 @@ module.exports = function llmsTxtPlugin(context) { base: '', isCurrent: true, }, + ...allVersions.slice(1).map((name) => ({ + name, + heading: name, + base: `/${name}`, + })), ]; const sections = []; diff --git a/static/img/gitbook/Token_house.png b/static/img/gitbook/Token_house.png new file mode 100644 index 0000000000..f9786333a0 Binary files /dev/null and b/static/img/gitbook/Token_house.png differ diff --git a/static/img/gitbook/image-1-1-1-1-1.png b/static/img/gitbook/image-1-1-1-1-1.png new file mode 100644 index 0000000000..b50aab6151 Binary files /dev/null and b/static/img/gitbook/image-1-1-1-1-1.png differ diff --git a/static/img/gitbook/image-3.png b/static/img/gitbook/image-3.png new file mode 100644 index 0000000000..ed58ded271 Binary files /dev/null and b/static/img/gitbook/image-3.png differ diff --git a/static/img/gitbook/image-51.png b/static/img/gitbook/image-51.png new file mode 100644 index 0000000000..16bcf6169d Binary files /dev/null and b/static/img/gitbook/image-51.png differ diff --git a/static/img/gitbook/image-53.png b/static/img/gitbook/image-53.png new file mode 100644 index 0000000000..760fade5d8 Binary files /dev/null and b/static/img/gitbook/image-53.png differ diff --git a/static/img/gitbook/image-87.png b/static/img/gitbook/image-87.png new file mode 100644 index 0000000000..b8d7d024f6 Binary files /dev/null and b/static/img/gitbook/image-87.png differ diff --git a/static/img/gitbook/image-88.png b/static/img/gitbook/image-88.png new file mode 100644 index 0000000000..06855731a4 Binary files /dev/null and b/static/img/gitbook/image-88.png differ diff --git a/static/img/gitbook/spaces_XeyaDcGpivHZJ18c2xxu_uploads_git-blob-9d5df062b767cf6cefe35e34437b25b1a0104f47_image-1.png b/static/img/gitbook/spaces_XeyaDcGpivHZJ18c2xxu_uploads_git-blob-9d5df062b767cf6cefe35e34437b25b1a0104f47_image-1.png new file mode 100644 index 0000000000..9d5df062b7 Binary files /dev/null and b/static/img/gitbook/spaces_XeyaDcGpivHZJ18c2xxu_uploads_git-blob-9d5df062b767cf6cefe35e34437b25b1a0104f47_image-1.png differ diff --git a/static/img/gitbook/stOBOL_03-3-1.png b/static/img/gitbook/stOBOL_03-3-1.png new file mode 100644 index 0000000000..21d5e1fce7 Binary files /dev/null and b/static/img/gitbook/stOBOL_03-3-1.png differ diff --git a/static/img/gitbook/stOBOL_03-3.png b/static/img/gitbook/stOBOL_03-3.png new file mode 100644 index 0000000000..21d5e1fce7 Binary files /dev/null and b/static/img/gitbook/stOBOL_03-3.png differ diff --git a/static/img/gitbook/stOBOL_03.png b/static/img/gitbook/stOBOL_03.png new file mode 100644 index 0000000000..7bd9c432d9 Binary files /dev/null and b/static/img/gitbook/stOBOL_03.png differ diff --git a/versioned_docs/version-v1.3/README.md b/versioned_docs/version-v1.3/README.md new file mode 100644 index 0000000000..9c0f8969bc --- /dev/null +++ b/versioned_docs/version-v1.3/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Introduction" +slug: /learn/introduction +--- + +# Introduction + diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..27650c3586 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# advanced + diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..7469ec868b --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 +``` diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..cb8e916119 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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](https://docs.obol.org/next/learn/intro/launchpad). + +### Pre-requisites[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#pre-requisites) {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#install-the-package) {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#instantiate-the-client) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#propose-the-cluster) {#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. + +```sh +// 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#invite-the-operators-to-complete-the-dkg) {#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](https://docs.obol.org/next/learn/intro/launchpad) to complete the process + +1. Operators navigate to `https://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](https://docs.obol.org/next/run/start/quickstart_group) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#retrieve-the-created-distributed-validators-using-the-sdk) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#activate-the-dvs-using-the-deposit-contract) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#usage-examples) {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..1b841329f4 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#getting-started-with-charon--the-builder-api) {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#client-configuration) {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#charon) {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#consensus-clients) {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](https://docs.obol.org/next/run/prepare/test-command#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#validator-clients) {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#verify-your-cluster-is-correctly-configured) {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [ultrasound relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..c44a11befc --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.3.3 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. +::: diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..720404af40 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,105 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.3.3 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..8c80d667f8 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,38 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency and decentralization, you can opt to host your own relay on a separate open and static internet port. + +```shell +# Figure out your public IP +curl v4.ident.me + +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your public IPv4 or DNS hostname + +nano relay/docker-compose.yml + +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +Note that a local `relay/.charon/charon-enr-private-key` file will be created next to `relay/docker-compose.yml` to ensure a persisted relay ENR across restarts. + +A list of publicly available relays that can be used is maintained [here](../security/risks.md). diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/README.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/README.md new file mode 100644 index 0000000000..08d9fd5147 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Security" +slug: /advanced-and-troubleshooting/security +--- + +# security + diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/bug-bounty.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/bug-bounty.md new file mode 100644 index 0000000000..06a57d0d34 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/bug-bounty.md @@ -0,0 +1,181 @@ +--- +description: "Bug Bounty Policy" +sidebar_label: "Obol Bug Bounty Program" +slug: /advanced-and-troubleshooting/security/bug-bounty +--- + +# Obol Bug Bounty Program + +## Overview + +At Obol Labs, we prioritize the security of our distributed validator software and related services. Our Bug Bounty Program is designed to encourage and reward security researchers for identifying and reporting potential vulnerabilities. This initiative supports our commitment to the security and integrity of our products. + +## Participant Eligibility + +Participants must meet the following criteria to be eligible for the Bug Bounty Program: + +- Not reside in countries where participation in such programs is prohibited. +- Be at least 14 years of age and possess the legal capacity to participate. +- Have received consent from your employer, if applicable. +- Not have been employed or contracted by Obol Labs, nor be an immediate family member of an employee, within the last 12 months. + +## Scope of the Program + +Eligible submissions must involve software and services developed by Obol, specifically under the domains of: + +- Charon the DV Middleware Client +- Obol DV Launchpad and Public API +- Obol Splits Contracts +- Obol Labs hosted Public Relay Infrastructure + +Submissions related to the following are considered out of scope: + +- Social engineering +- Rate Limiting (Non-critical issues) +- Physical security breaches +- Non-security related UX/UI issues +- Third-party application vulnerabilities +- The [Obol](https://obol.org) static website or the Obol infrastructure +- The operational security of node operators running or using Obol software + +## Program Rules + +- Submitted bugs must not have been previously disclosed publicly. +- Only first reports of vulnerabilities will be considered for rewards; previously reported or known vulnerabilities are ineligible. +- The severity of the vulnerability, as assessed by our team, will determine the reward amount. See the "Rewards" section for details. +- Submissions must include a reproducible proof of concept. +- The Obol security team reserves the right to determine the eligibility and reward for each submission. +- Program terms may be updated at Obol's discretion. +- Valid bugs may be disclosed to partner protocols within the Obol ecosystem to enhance overall security. + +## Rewards Structure + +Rewards are issued based on the severity and impact of the disclosed vulnerability, determined at the discretion of Obol Labs. + +### Critical Vulnerabilities: Up to $100,000 + +A Critical-level vulnerability is one that has a severe impact on the security of the in-production system from an unauthenticated external attacker, and requires immediate attention to fix. Highly likely to have a material impact on validator private key security, and/or loss of funds. + +- High impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully exfiltrate BLS (not K1) private key material from a threshold number of operators in the cluster. +- Attacker that is not a member of the cluster can achieve the production of arbitrary BLS signatures from a threshold number of operators in the cluster. +- Attacker can craft a malicious cluster invite capable of subverting even careful review of all data to steal funds during a deposit. +- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield +- Direct loss of funds +- Permanent freezing of funds (fix requires hard fork) +- Network not being able to confirm new transactions (Total network shutdown) +- Protocol insolvency + +### High Vulnerabilities: Up to $10,000 + +For significant security risks that impact the system from a position of low-trust and require a significant effort to fix. + +- High impact, medium likelihood +- Medium impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully partition the cluster and keep the cluster offline indefinitely. +- Attacker that is not a member of the cluster can exfiltrate Charon ENR private keys. +- Attacker that is not a member of the cluster can destroy funds but cannot steal them. +- Unintended chain split (Network partition) +- Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments +- RPC API crash affecting projects with greater than or equal to 25% of the market capitalization on top of the respective layer +- Theft of unclaimed yield +- Theft of unclaimed royalties +- Permanent freezing of unclaimed yield +- Permanent freezing of unclaimed royalties +- Temporary freezing of funds +- Retrieve sensitive data/files from a running server: + - blockchain keys + - database passwords + - (this does not include non-sensitive environment variables, open source code, or usernames) +- Taking state-modifying authenticated actions (with or without blockchain state interaction) on behalf of other users without any interaction by that user, such as: + - Changing cluster information + - Withdrawals + - Making trades + +### Medium Vulnerabilities: Up to $2,500 + +For vulnerabilities with a moderate impact, affecting system availability or integrity. + +- High impact, low likelihood +- Medium impact, medium likelihood +- Low impact, high likelihood + +Impacts: + +- Attacker that is a member of a cluster can exfiltrate K1 key material from another member. +- Attacker that is a member of the cluster can denial of service attack enough peers in the cluster to prevent operation of the validator(s) +- Attacker that is a member of the cluster can bias the protocol in a manner to control the majority of block proposal opportunities. +- Attacker can get a DV Launchpad user to inadvertently interact with a smart contract that is not a part of normal operation of the launchpad. +- Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours +- Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network +- Charon cluster identity private key theft +- Rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle +- Charon public relay node is compromised and leads to cluster topologies getting discovered and disrupted +- Smart contract unable to operate due to lack of token funds +- Block stuffing +- Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol) +- Theft of gas +- Unbounded gas consumption +- Redirecting users to malicious websites (Open Redirect) + +### Low Vulnerabilities: Up to $500 + +For vulnerabilities with minimal impact, unlikely to significantly affect system operations. + +- Low impact, medium likelihood +- Medium impact, low likelihood + +Impacts: + +- Attacker can sometimes put a Charon node in a state that causes it to drop one out of every one hundred attestations made by a validator +- Attacker can display bad data on a non-interactive part of the launchpad. +- Contract fails to deliver promised returns, but doesn't lose value +- Shutdown of greater than 10% or equal to but less than 30% of network processing nodes without brute force actions, but does not shut down the network +- Changing details of other users (including modifying browser local storage) without already-connected wallet interaction and with significant user interaction such as: + - Iframing leading to modifying the backend/browser state (must demonstrate impact with PoC) +- Taking over broken or expired outgoing links such as: + - Social media handles, etc. +- Temporarily disabling user to access target site, such as: + - Locking up the victim from login + - Cookie bombing, etc. + +Rewards may be issued as cash, merchandise, or other forms of recognition, at Obol's discretion. Only one reward will be granted per unique vulnerability. + +## The following activities are prohibited by this bug bounty program + +- Any testing on mainnet or public testnet deployed code; all testing should be done on local-forks of either public testnet or mainnet +- Any testing with pricing oracles or third-party smart contracts +- Attempting phishing or other social engineering attacks against our employees and/or customers +- Any testing with third-party systems and applications (e.g. browser extensions) as well as websites (e.g. SSO providers, advertising networks) +- Any denial of service attacks that are executed against project assets +- Automated testing of services that generate significant amounts of traffic +- Public disclosure of an unpatched vulnerability in an embargoed bounty + +## Submission process + +To report a vulnerability, please contact us at security@obol.tech with: + +- A detailed description of the vulnerability and its potential impact. +- Steps to reproduce the issue. +- Any relevant proof of concept code, screenshots, or documentation. +- Your contact information. + +Incomplete reports may not be eligible for rewards. + +## Disclosure and Confidentiality + +Obol Labs will disclose vulnerabilities and the identity of the researcher (with consent) after remediation. Researchers are required to maintain confidentiality until official disclosure by Obol Labs. + +## Legal and Ethical Compliance + +Participants must adhere to all relevant laws and regulations. Obol Labs will not pursue legal action against researchers reporting vulnerabilities in good faith, but reserves the right to respond to violations of this policy. + +## Non-Disclosure Agreement (NDA) + +Participants may be required to sign an NDA for access to certain proprietary information during their research. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/contact.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/contact.md new file mode 100644 index 0000000000..0b4b54d4fd --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/contact.md @@ -0,0 +1,11 @@ +--- +description: "Security details for the Obol Network" +sidebar_label: "Contacts" +slug: /advanced-and-troubleshooting/security/contact +--- + +# Contacts + +Please email security@obol.tech to report a security incident, vulnerability, bug or inquire about Obol's security. + +Also, visit the [obol security repo](https://github.com/ObolNetwork/obol-security) for more details. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/ev-assessment.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/ev-assessment.md new file mode 100644 index 0000000000..3a666bf1e8 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/ev-assessment.md @@ -0,0 +1,293 @@ +--- +description: "Software Development Security Assessment" +sidebar_label: "Software Development at Obol" +slug: /advanced-and-troubleshooting/security/ev-assessment +--- + +# Software Development at Obol + +When hardening a projects technical security, team member's operational security, and the security of the software development practices in use by the team are some of the most criticial areas to secure. Many hacks and compromises in the space to date have been a result of these attack vectors rather than exploits of the software itself. + +With this in mind, in January 2023 the Obol team retained the expertise of Ethereal Venture's security researcher Alex Wade; to interview key stakeholders and produce a report into the teams Software Development Lifecycle. + +The below page is a result of the report that was produced. What is present here has had some sensitive information redacted, and contains responses to the recommendations made, detailing the actions the Obol team have taken to mitigate what has been highlighted. + +## Obol Report + +**Prepared by: Alex Wade (Ethereal Ventures)** **Date: Jan 2023** + +Over the past month, I worked with Obol to review their software development practices in preparation for their upcoming security audits. My goals were to review and analyze: + +* Software development processes +* Vulnerability disclosure and escalation procedures +* Key personnel risk + +The information in this report was collected through a series of interviews with Obol’s project leads. + +## Contents + +* Background Info +* Analysis - Cluster Setup and DKG + * Key Risks + * Potential Attack Scenarios +* Recommendations + * R1: Users should deploy cluster contracts through a known on-chain entry point + * R2: Users should deposit to the beacon chain through a pool contract + * R3: Raise the barrier to entry to push an update to the Launchpad +* Additional Notes + * Vulnerability Disclosure + * Key Personnel Risk + +## Background Info + +**Each team lead was asked to describe Obol in terms of its goals, objectives, and key features.** + +### What is Obol? + +Obol builds DVT (Distributed Validator Technology) for Ethereum. + +### What is Obol’s goal? + +Obol’s goal is to solve a classic distributed systems problem: uptime. + +Rather than requiring Ethereum validators to stake on their own, Obol allows groups of operators to stake together. Using Obol, a single validator can be run cooperatively by multiple people across multiple machines. + +In theory, this architecture provides validators with some redundancy against common issues: server and power outages, client failures, and more. + +### What are Obol’s objectives? + +Obol’s business objective is to provide base-layer infrastructure to support a distributed validator ecosystem. As Obol provides base layer technology, other companies and projects will build on top of Obol. + +Obol’s business model is to eventually capture a portion of the revenue generated by validators that use Obol infrastructure. + +### What is Obol’s product? + +Obol’s product consists of three main components, each run by its own team: a webapp, a client, and smart contracts. + +* [DV Launchpad](../../learn/intro/launchpad.md): A webapp to create and manage distributed validators. +* [Charon](../../learn/charon/intro.md): A middleware client that enables operators to run distributed validators. +* [Solidity](../../learn/intro/obol-splits.md): Withdrawal and fee recipient contracts for use with distributed validators. + +## Analysis - Cluster Setup and DKG + +The Launchpad guides users through the process of creating a cluster, which defines important parameters like the validator’s fee recipient and withdrawal addresses, as well as the identities of the operators in the cluster. In order to ensure their cluster configuration is correct, users need to rely on a few different factors. + +**First, users need to trust the Charon client** to perform the DKG correctly, and validate things like: + +* Config file is well-formed and is using the expected version +* Signatures and ENRs from other operators are valid +* Cluster config hash is correct +* DKG succeeds in producing valid signatures +* Deposit data is well-formed and is correctly generated from the cluster config and DKG. + +However, Charon’s validation is limited to the digital: signature checks, cluster file syntax, etc. It does NOT help would-be operators determine whether the other operators listed in their cluster definition are the real people with whom they intend to start a DVT cluster. So - + +**Second, users need to come to social consensus with fellow operators.** While the cluster is being set up, it’s important that each operator is an active participant. Each member of the group must validate and confirm that: + +* the cluster file correctly reflects their address and node identity, and reflects the information they received from fellow operators +* the cluster parameters are expected – namely, the number of validators and signing threshold + +**Finally, users need to perform independent validation.** Each user should perform their own validation of the cluster definition: + +* Is my information correct? (address and ENR) +* Does the information I received from the group match the cluster definition? +* Is the ETH2 deposit data correct, and does it match the information in the cluster definition? +* Are the withdrawal and fee recipient addresses correct? + +These final steps are potentially the most difficult, and may require significant technical knowledge. + +## Key Risks + +### 1. Validation of Contract Deployment and Deposit Data Relies Heavily on Launchpad + +From my interviews, it seems that the user deploys both the withdrawal and fee recipient contracts through the Launchpad. + +What I’m picturing is that during the first parts of the cluster setup process, the user is prompted to sign one or more transactions deploying the withdrawal and fee recipient contracts to mainnet. The Launchpad apparently uses an npm package to deploy these contracts: `0xsplits/splits-sdk`, which I assume provides either JSON artifacts or a factory address on chain. The Launchpad then places the deployed contracts into the cluster config file, and the process moves on. + +If an attacker has published a malicious update to the Launchpad (or compromised an underlying dependency), the contracts deployed by the Launchpad may be malicious. The questions I’d like to pose are: + +* How does the group creator know the Launchpad deployed the correct contracts? +* How does the rest of the group know the creator deployed the contracts through the Launchpad? + +My understanding is that this ultimately comes down to the independent verification that each of the group’s members performs during and after the cluster’s setup phase. + +At its worst, this verification might consist solely of the cluster creator confirming to the others that, yes, those addresses match the contracts I deployed through the Launchpad. + +A more sophisticated user might verify that not only do the addresses match, but the deployed source code looks roughly correct. However, this step is far out of the realm of many would-be validators. To be really certain that the source code is correct would require auditor-level knowledge. + +The risk is that: + +* the deployed contracts are NOT the correctly-configured 0xsplits waterfall/fee splitter contracts +* most users are ill-equipped to make this determination themselves +* we don’t want to trust the Launchpad as the single source of truth + +In the worst case, the cluster may end up depositing with malicious withdrawal or fee recipient credentials. If unnoticed, this may net an attacker the entire withdrawal amount, once the cluster exits. + +Note that the same (or similar) risks apply to validation of deposit data, which has the potential to be similarly difficult. I’m a little fuzzy on which part of the Obol stack actually generates the deposit data / deposit transaction, so I can’t speak to this as much. However, I think the mitigation for both of these is roughly the same - read on! + +**Mitigation:** + +It’s certainly a good idea to make it harder to deploy malicious updates to the Launchpad, but this may not be entirely possible. A higher-yield strategy may be to educate and empower users to perform independent validation of the DVT setup process - without relying on information fed to them by Charon and the Launchpad. + +I’ve outlined some ideas for this in #R1 and #R2. + +### 2. Social Consensus, aka “Who sends the 32 ETH?” + +Depositing to the beacon chain requires a total of 32 ETH. Obol’s product allows multiple operators to act as a single validator together, which means would-be operators need to agree on how to fund the 32 ETH needed to initiate the deposit. + +It is my understanding that currently, this process comes down to trust and loose social consensus. Essentially, the group needs to decide who chips in what amount together, and then trust someone to take the 32 ETH and complete the deposit process correctly (without running away with the money). + +Granted, the initial launch of Obol will be open only to a small group of people as the kinks in the system get worked out - but in preparation for an eventual public release, the deposit process needs to be much simpler and far less reliant on trust. + +Mitigation: See #R2. + +**Potential Attack Scenarios** + +During the interview process, I learned that each of Obol’s core components has its own GitHub repo, and that each repo has roughly the same structure in terms of organization and security policies. For each repository: + +* There are two overall github organization administrators, and a number of people have administrative control over individual repositories. +* In order to merge PRs, the submitter needs: + * CI/CD checks to pass + * Review from one person (anyone at Obol) + +Of course, admin access also means the ability to change these settings - so repo admins could theoretically merge PRs without needing checks to pass, and without review/approval, organization admins can control the full GitHub organization. + +The following scenarios describe the impact an attack may have. + +**1. Publishing a malicious version of the Launchpad, or compromising an underlying dependency** + +* Reward: High +* Difficulty: Medium-Low + +As described in Key Risks, publishing a malicious version of the Launchpad has the potential to net the largest payout for an attacker. By tampering with the cluster’s deposit data or withdrawal/fee recipient contracts, an attacker stands to gain 32 ETH or more per compromised cluster. + +During the interviews, I learned that merging PRs to main in the Launchpad repo triggers an action that publishes to the site. Given that merges can be performed by an authorized Obol developer, this makes the developers prime targets for social engineering attacks. + +Additionally, the use of the `0xsplits/splits-sdk` NPM package to aid in contract deployment may represent a supply chain attack vector. It may be that this applies to other Launchpad dependencies as well. + +In any case, with a fairly large surface area and high potential reward, this scenario represents a credible risk to users during the cluster setup and DKG process. + +See #R1, #R2, and #R3 for some ideas to address this scenario. + +**2. Publishing a malicious version of Charon to new operators** + +* Reward: Medium +* Difficulty: High + +During the cluster setup process, Charon is responsible both for validating the cluster configuration produced by the Launchpad, as well as performing a DKG ceremony between a group’s operators. + +If new operators use a malicious version of Charon to perform this process, it may be possible to tamper with both of these responsibilities, or even get access to part or all of the underlying validator private key created during DKG. + +However, the difficulty of this type of attack seems quite high. An attacker would first need to carry out the same type of social engineering attack described in scenario 1 to publish and tag a new version of Charon. Crucially, users would also need to install the malicious version - unlike the Launchpad, an update here is not pushed directly to users. + +As long as Obol is clear and consistent with communication around releases and versioning, it seems unlikely that a user would both install a brand-new, unannounced release, and finish the cluster setup process before being warned about the attack. + +**3. Publishing a malicious version of Charon to existing validators** + +* Reward: Low +* Difficulty: High + +Once a distributed validator is up and running, much of the danger has passed. As a middleware client, Charon sits between a validator’s consensus and validator clients. As such, it shouldn’t have direct access to a validator’s withdrawal keys nor signing keys. + +If existing validators update to a malicious version of Charon, it’s likely the worst thing an attacker could theoretically do is slash the validator, however, assuming Charon has no access to any private keys, this would be predicated on one or more validator clients connected to Charon also failing to prevent the signing of a slashable message. In practice, a compromised Charon client is more likely to pose liveness risks than safety risks. + +This is not likely to be particularly motivating to potential attackers - and paired with the high difficulty described above, this scenario seems unlikely to cause significant issues. + +## Recommendations + +### R1: Users should deploy cluster contracts through a known on-chain entry point + +During setup, users should only sign one transaction via the Launchpad - to a contract located at an Obol-held ENS (e.g. `launchpad.obol.eth`). This contract should deploy everything needed for the cluster to operate, like the withdrawal and fee recipient contracts. It should also initialize them with the provided reward split configuration (and any other config needed). + +Rather than using an NPM library to supply a factory address or JSON artifacts, this has the benefit of being both: + +* **Harder to compromise:** as long as the user knows launchpad.obol.eth, it’s pretty difficult to trick them into deploying the wrong contracts. +* **Easier to validate** for non-technical users: the Obol contract can be queried for deployment information via etherscan. For example:\ + ![](/img/gitbook/image-50.png) + +Note that in order for this to be successful, Obol needs to provide detailed steps for users to perform manual validation of their cluster setups. Users should be able to treat this as a “checklist:” + +* Did I send a transaction to `launchpad.obol.eth`? +* Can I use the ENS name to locate and query the deployment manager contract on etherscan? +* If I input my address, does etherscan report the configuration I was expecting? + * withdrawal address matches + * fee recipient address matches + * reward split configuration matches + +As long as these steps are plastered all over the place (i.e. not just on the Launchpad) and Obol puts in effort to educate users about the process, this approach should allow users to validate cluster configurations themselves - regardless of Launchpad or NPM package compromise. + +**Obol’s response** + +Roadmapped: add the ability for the OWR factory to claim and transfer its reverse resolution ownership. + +### R2: Users should deposit to the beacon chain through a pool contract + +Once cluster setup and DKG is complete, a group of operators should deposit to the beacon chain by way of a pool contract. The pool contract should: + +* Accept Eth from any of the group’s operators +* Stop accepting Eth when the contract’s balance hits (32 ETH \* number of validators) +* Make it easy to pull the trigger and deposit to the beacon chain once the critical balance has been reached +* Offer all of the group’s operators a “bail” option at any point before the deposit is triggered + +Ideally, this contract is deployed during the setup process described in #R1, as another step toward allowing users to perform independent validation of the process. + +Rather than relying on social consensus, this should: + +* Allow operators to fund the validator without needing to trust any single party +* Make it harder to mess up the deposit or send funds to some malicious actor, as the pool contract should know what the beacon deposit contract address is + +**Obol’s response** + +Roadmapped: give the operators a streamlined, secure way to deposit Ether (ETH) to the beacon chain collectively, satisfying specific conditions: + +* Pooling from multiple operators. +* Ceasing to accept ETH once a critical balance is reached, defined by 32 ETH multiplied by the number of validators. +* Facilitating an immediate deposit to the beacon chain once the target balance is reached. +* Provide a 'bail-out' option for operators to withdraw their contribution before initiating the group's deposit to the beacon chain. + +### R3: Raise the barrier to entry to push an update to the Launchpad + +Currently, any repo admin can publish an update to the Launchpad unchecked. + +Given the risks and scenarios outlined above, consider amending this process so that the sole compromise of either admin is not sufficient to publish to the Launchpad site. It may be worthwhile to require both admins to approve publishing to the site. + +Along with simply adding additional prerequisites to publish an update to the Launchpad, ensure that both admins have enabled some level of multi-factor authentication on their GitHub accounts. + +**Obol’s response** + +We removed individual’s ability to merge changes without review, enforced MFA, signed commits, and employed Bulldozer bot to make sure a PR gets merged automatically when all checks pass. + +## Additional Notes + +### Vulnerability Disclosure + +During the interviews, I got some conflicting information when asking about Obol’s vulnerability disclosure process. + +Some interviewees directed me towards Obol’s security repo, which details security contacts: [ObolNetwork/obol-security](https://github.com/ObolNetwork/obol-security), while some answered that disclosure should happen primarily through Immunefi. While these may both be part of the correct answer, it seems that Obol’s disclosure process may not be as well-defined as it could be. Here are some notes: + +* I wasn’t able to find information about Obol on Immunefi. I also didn’t find any reference to a security contact or disclosure policy in Obol’s docs. +* When looking into the obol security repo, I noticed broken links in a few of the sections in README.md and SECURITY.md: + * Security policy + * More Information +* Some of the text and links in the Bug Bounty Program don’t seem to apply to Obol (see text referring to Vaults and Strategies). +* The Receiving Disclosures section does not include a public key with which submitters can encrypt vulnerability information. + +It’s my understanding that these items are probably lower priority due to Obol’s initial closed launch - but these should be squared away soon! \[Obol response to latest vuln disclosure process goes here] + +**Obol’s response** + +we addressed all of the concerns in the obol-security repository: + +1. The security policy link has been fixed +2. The Bug Bounty program received an overhaul and clearly states rewards, eligibility, and scope +3. We list two GPG public keys for which we accept encrypted vulnerabilities reports. + +We are actively working towards integrating Immunefi in our security pipeline. + +### Key Personnel Risk + +A final section on the specifics of key personnel risk faced by Obol has been redacted from the original report. Particular areas of control highlighted were github org ownership and domain name control. + +**Obol’s response** + +These risks have been mitigated by adding an extra admin to the github org, and by setting up a second DNS stack in case the primary one fails, along with general Opsec improvements. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/overview.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/overview.md new file mode 100644 index 0000000000..1ea44b17b2 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/overview.md @@ -0,0 +1,37 @@ +--- +description: "Security Overview" +sidebar_label: "Overview" +slug: /advanced-and-troubleshooting/security/overview +--- + +# Overview + +This page serves as an overview of the Obol Network from a security point of view. + +This page is updated quarterly. The last update was on 2024-June-19. + +## Table of Contents + +* [Overview](overview.md) + * [Table of Contents](overview.md#table-of-contents) + * [List of Security Audits and Assessments](overview.md#list-of-security-audits-and-assessments) + * [Security focused documents](overview.md#security-focused-documents) + * [Bug Bounty](overview.md#bug-bounty) + +## List of Security Audits and Assessments + +The completed audits reports are linked [here](https://github.com/ObolNetwork/obol-security/tree/main/audits). + +* A review of Obol Labs [development processes](./ev-assessment.md) by [Ethereal Ventures](https://www.etherealventures.com/). +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/) resulting in version [`v0.16.0`](https://github.com/ObolNetwork/charon/releases/tag/v0.16.0). +* A second [assessment of Charon](https://obol.tech/charon_quantstamp_assessment.pdf) by [QuantStamp](https://quantstamp.com/) resulting in version [`v0.19.1`](https://github.com/ObolNetwork/charon/releases/tag/v0.19.1). +* A [solidity audit](./smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* A [penetration testing certificate](https://github.com/ObolNetwork/obol-security/blob/main/audits/Sayfer_2024-03_Penetration_Testing_CFD.pdf) of the Obol DV Launchpad by [Sayfer](https://sayfer.io/). + +## Security focused documents + +* A [threat model](./threat_model.md) for a DV middleware client like Charon. + +## Bug Bounty + +Information related to disclosing bugs and vulnerabilities to Obol can be found on [the next page](bug-bounty.md). diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/risks.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/risks.md new file mode 100644 index 0000000000..52a8d63881 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/risks.md @@ -0,0 +1,45 @@ +--- +description: "Centralization Risks and mitigation" +sidebar_label: "Centralization Risks and Mitigation" +slug: /advanced-and-troubleshooting/security/risks +--- + +# Centralization Risks and Mitigation + +## Risk: Obol hosting the relay infrastructure + +**Mitigation**: Self-host a relay. + +One of the risks associated with Obol hosting the [LibP2P relays](../../learn/charon/charon-networking.md) infrastructure allowing peer discovery is that if Obol-hosted relays go down, peers won't be able to discover each other and perform the DKG. To mitigate this risk, external organizations and node operators can consider self-hosting a relay. This way, if Obol's relays go down, the clusters can still operate through other relays in the network. Ensure that all nodes in the cluster use the same relays, or they will not be able to find each other if they are connected to different relays. + +The following non-Obol entities run relays that you can consider adding to your cluster (you can have more than one per cluster, see the `--p2p-relays` flag of [`charon run`](../../learn/charon/charon-cli-reference.md#the-run-command)): + +| Entity | Relay URL | +| ------------------------------------------- | ------------------------------------ | +| [DSRV](https://www.dsrvlabs.com/) | https://charon-relay.dsrvlabs.dev | +| [Infstones](https://infstones.com/) | https://obol-relay.infstones.com/ | +| [Hashquark](https://www.hashquark.io/) | https://relay-2.prod-relay.721.land/ | +| [Figment](https://figment.io/) | https://relay-1.obol.figment.io/ | +| [Node Guardians](https://nodeguardians.io/) | https://obol-relay.nodeguardians.io/ | + +## Risk: Obol being able to update Charon code + +**Mitigation**: Pin specific docker versions or compile from source on a trusted commit. + +Another risk associated with Obol is the Labs team having the ability to update the [Charon code](https://github.com/ObolNetwork/charon) used by node operators within DV clusters, which could introduce vulnerabilities or malicious code. To mitigate this risk, operators can consider pinning specific versions of the Docker image or git repo that have been [thoroughly tested](overview.md#list-of-security-audits-and-assessments) and accepted by the network. This would ensure that any updates are carefully vetted and reviewed by the community, and only introduced into a running cluster gradually. The labs team will strive to communicate the security or operational impact any Charon update entails, giving operators the chance to decide whether they want potential performance or quality of experience improvements, or whether they remain on a trusted version for longer. + +## Risk: Obol hosting the DV Launchpad + +**Mitigation**: Use [`create cluster`](../../learn/charon/charon-cli-reference.md#the-create-command) or [`create dkg`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) locally and distribute the files manually. + +Hosting the first Charon frontend, the [DV Launchpad](../../learn/intro/launchpad.md), on a centralized server could create a single point of failure, as users would have to rely on Obol's server to access the protocol. This could limit the decentralization of the protocol and could make it vulnerable to attacks or downtime. Obol hosting the launchpad on a decentralized network, such as IPFS is a first step but not enough. This is why the Charon code is open-source and contains a CLI interface to interact with the protocol locally. + +To mitigate the risk of launchpad failure, consider using the `create cluster` or `create dkg` commands locally and distributing the key shares files manually. + +## Risk: Obol going bust/rogue + +**Mitigation**: Use key recovery. + +The final centralization risk associated with Obol is the possibility of the company going bankrupt or acting maliciously, which would lead to a loss of control over the network and potentially cause damage to the ecosystem. To mitigate this risk, Obol has implemented a key recovery mechanism. This would allow the clusters to continue operating and to retrieve full private keys even if Obol is no longer able to provide support. + +A guide to recombine key shares into a single private key can be accessed [here](../advanced/quickstart-combine.md). diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/smart-contract-audit.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/smart-contract-audit.md new file mode 100644 index 0000000000..1872d523d8 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/smart-contract-audit.md @@ -0,0 +1,467 @@ +--- +sidebar_label: "Smart Contract Audit" +slug: /advanced-and-troubleshooting/security/smart-contract-audit +--- + +# Smart Contract Audit + +## Obol Audit Report: Obol Manager Contracts + +Prepared by: Zach Obront, Independent Security Researcher + +Date: Sept 18 to 22, 2023 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/Obol%20Audit%20Report.pdf) + +### About **Obol**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-obol) {#about-obol} +The Obol Network is an ecosystem for trust minimized staking that enables people to create, test, run & co-ordinate distributed validators. + +The Obol Manager contracts are responsible for distributing validator rewards and withdrawals among the validator and node operators involved in a distributed validator. + +### About **zachobront**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-zachobront) {#about-zachobront} +Zach Obront is an independent smart contract security researcher. He serves as a Lead Senior Watson at Sherlock, a Security Researcher at Spearbit, and has identified multiple critical severity bugs in the wild, including in a Top 5 Protocol on Immunefi. You can say hi on Twitter at [@zachobront](http://twitter.com/zachobront). + +### Summary & Scope[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary--scope) {#summary--scope} +The [ObolNetwork/obol-manager-contracts](https://github.com/ObolNetwork/obol-manager-contracts/) repository was audited at commit [50ce277919723c80b96f6353fa8d1f8facda6e0e](https://github.com/ObolNetwork/obol-manager-contracts/tree/50ce277919723c80b96f6353fa8d1f8facda6e0e). + +The following contracts were in scope: + +* src/controllers/ImmutableSplitController.sol +* src/controllers/ImmutableSplitControllerFactory.sol +* src/lido/LidoSplit.sol +* src/lido/LidoSplitFactory.sol +* src/owr/OptimisticWithdrawalReceiver.sol +* src/owr/OptimisticWithdrawalReceiverFactory.sol + +After completion of the fixes, the [2f4f059bfd145f5f05d794948c918d65d222c3a9](https://github.com/ObolNetwork/obol-manager-contracts/tree/2f4f059bfd145f5f05d794948c918d65d222c3a9) commit was reviewed. After this review, the updated Lido fee share system in [PR #96](https://github.com/ObolNetwork/obol-manager-contracts/pull/96/files) (at commit [fd244a05f964617707b0a40ebb11b523bbd683b8](https://github.com/ObolNetwork/obol-splits/pull/96/commits/fd244a05f964617707b0a40ebb11b523bbd683b8)) was reviewed. + +### Summary of Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary-of-findings) {#summary-of-findings} +| Identifier | Title | Severity | Fixed | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------- | ----- | +| [M-01](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) | Future fees may be skirted by setting a non-ETH reward token | Medium | ✓ | +| [M-02](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) | Splits with 256 or more node operators will not be able to switch on fees | Medium | ✓ | +| [M-03](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) | In a mass slashing event, node operators are incentivized to get slashed | Medium | | +| [L-01](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) | Obol fees will be applied retroactively to all non-distributed funds in the Splitter | Low | ✓ | +| [L-02](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) | If OWR is used with rebase tokens and there's a negative rebase, principal can be lost | Low | ✓ | +| [L-03](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) | LidoSplit can receive ETH, which will be locked in contract | Low | ✓ | +| [L-04](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) | Upgrade to latest version of Solady to fix LibClone bug | Low | ✓ | +| [G-01](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) | stETH and wstETH addresses can be saved on implementation to save gas | Gas | ✓ | +| [G-02](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) | OWR can be simplified and save gas by not tracking distributedFunds | Gas | ✓ | +| [I-01](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) | Strong trust assumptions between validators and node operators | Informational | | +| [I-02](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) | Provide node operator checklist to validate setup | Informational | | + +### Detailed Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#detailed-findings) {#detailed-findings} +#### \[M-01] Future fees may be skirted by setting a non-ETH reward token[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) {#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token} +Fees are planned to be implemented on the `rewardRecipient` splitter by updating to a new fee structure using the `ImmutableSplitController`. + +It is assumed that all rewards will flow through the splitter, because (a) all distributed rewards less than 16 ETH are sent to the `rewardRecipient`, and (b) even if a team waited for rewards to be greater than 16 ETH, rewards sent to the `principalRecipient` are capped at the `amountOfPrincipalStake`. + +This creates a fairly strong guarantee that reward funds will flow to the `rewardRecipient`. Even if a user were to set their `amountOfPrincipalStake` high enough that the `principalRecipient` could receive unlimited funds, the Obol team could call `distributeFunds()` when the balance got near 16 ETH to ensure fees were paid. + +However, if the user selects a non-ETH token, all ETH will be withdrawable only thorugh the `recoverFunds()` function. If they set up a split with their node operators as their `recoveryAddress`, all funds will be withdrawable via `recoverFunds()` without ever touching the `rewardRecipient` or paying a fee. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation) + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept) + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-1) + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-1) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendations) + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-2) + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-2) + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-3) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-3) + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-4) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-1) + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-4) + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-5) + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-2) + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-5) + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-6) + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-6) + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-7) + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-7) + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-8) + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-9) + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-10) + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\ diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..c4221f103f --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,156 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritize the liveliness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalize operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator.\ +A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..1ed84c4d89 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# troubleshooting + diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..a8ffa31bec --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,290 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting anything other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using + +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +For now, ENR rotation/replacement is not supported, it will be supported in a future release. Therefore, its advised to always keep a backup of your `charon-enr-private-key` in a secure location (ex: cloud storage, USB Flash drive, etc.). + +### I can't find the keys anywhere + +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows.\ +Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + +## Lighthouse + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + +### Lighthouse gives the error `not enough time for a discovery seach` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues + +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance.\ +Using 3rd party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is\ +probably not online to sign successfully. Make sure all operators are\ +running the latest version of Charon. To check if some peers are not online:`docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key\ +should be created and placed in the right directory during the ceremony.\ +Also, make sure you are working in the right directory:`charon-distributed-validator-node`. + +### `Failed to confirm node connection` + +Wait for Teku & Lighthouse sync to be complete. + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum\ +limit has been reached. This is most often due to "maximum reservations per IP/peer".\ +This is when your Charon node is restarting or in some error loop and constantly\ +attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it.\ +This should allow the relay enough time to reset your IP/peer limits and\ +should then allow new reservations. This could also be due to the relay\ +being overloaded in general, so reaching a server wide "maximum connections"\ +limit. This is an issue with relay scalability and we are working in a long\ +term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO\_RESERVATION (204)\` indicates the peer\ +isn't connected to the relay, so the the Charon client cannot connect to the\ +peer via the relay. That might be because the peer is offline or the peer is\ +configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact\ +same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when\ +it failed to fetch the required data from the beacon node API. This indicates\ +a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation\ +duty failed in the fetcher component since it couldn't fetch the prerequisite\ +attestation data. This indicates the associated attestation duty failed to obtain\ +a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation\ +duty failed in the fetcher component since it couldn't fetch the prerequisite\ +aggregated v2 committee subscription. This indicates the associated prepare aggregation\ +duty failed due to no partial v2 committee subscription submitted by the cluster\ +validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation\ +duty failed in the fetcher component since it couldn't fetch the prerequisite\ +aggregated v2 committee subscription. This indicates the associated prepare aggregation\ +duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed\ +in the fetcher component since it couldn't fetch the prerequisite aggregated\ +RANDAO. This indicates the associated randao duty failed due to insufficient\ +partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed\ +in the fetcher component since it couldn't fetch the prerequisite aggregated\ +RANDAO. This indicates the associated randao duty failed due to no partial randao\ +signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed\ +in the fetcher component since it couldn't fetch the prerequisite aggregated\ +RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This\ +could indicate that insufficient honest peers participated in consensus or p2p\ +network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted\ +by the local validator client. This could indicate that the local validator client\ +is offline, or has connection problems with Charon, or has some other problem.\ +See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database\ +as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was\ +received from any peer. This indicates all peers are offline or p2p network connection\ +problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures\ +for the duty was received from peers. This indicates problems with peers or p2p\ +network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient\ +partial signatures failed. This indicates inconsistent signed data. This indicates\ +a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it\ +checks for a special file called the private key lock file. This file has the\ +same name as the ENR private key file but with a `.lock` extension.\ +If the private key lock file exists and is not older than 5 seconds, Charon won't\ +run. It doesn't allow running multiple Charon instances with the same ENR private\ +key. If the private key lock file has a timestamp older than 5 seconds, Charon\ +will replace it and continue with its work. If you\`re sure that no other Charon\ +instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the\ +validators private key shares don't match the ENR private key. There may\ +have been a mix-up during deployment, leading to a mismatching validator\ +client key share index. + +For example:Imagine node N is Alice, and node M is Bob, the error would read:`mismatching validator client key share index, Bob`s key share submitted to Alice`s charon node` Bob`s private key share(s) are imported to a VC that is connected to Alice`s Charon node. This is a invalid setup/deployment.\ +Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside\ +cluster-lock.json and see that matches with the public key inside`node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data first time around.\ +You can solve this by following the steps below: + +* Click the Wheel Icon > Datasources. +* Click prometheus. +* Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +* Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel + +Can be linked to a Teku keystore issue. + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + +``` +You can ignore this error unless you have been contacted by the Obol Team +with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. +``` + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly\ +on Linux and WSL for Windows systems. In the interest of security, the\ +charon docker image runs as a non-root user, and this user often does not\ +have the permissions to write in the directory you have checked out the code\ +to. This can be generally be fixed with some of the following: + +* Running docker commands with `sudo`, if you haven't [setup docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +* Changing the permissions of the `.charon` folder with the commands: + * `mkdir .charon` (if it doesn't already exist); + * `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + +``` +It`s because both Nethermind and Lighthouse start syncing and so there's +connectivity issues among the containers. Simply let the containers run for +a while. You won't observe frequent errors when Nethermind finishes syncing. You +can also add a second beacon node endpoint for something like Infura by +adding a comma separated API URL to the end of +`CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. +``` + +### How do I fix the `plugin "loki" not found` error? + +If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + +## Relay + +### `Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the\ +relay/docker-compose.yml with your real public IP or DNS hostname. + +### `Timeout resolving bootnode ENR: context deadline exceeded` + +The relay you are trying to connect to your peers via is offline or\ +unreachable. diff --git a/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..d10b59653d --- /dev/null +++ b/versioned_docs/version-v1.3/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or un-conctactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.3/api/address.mdx b/versioned_docs/version-v1.3/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.3/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.3/api/cluster-definition.mdx b/versioned_docs/version-v1.3/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.3/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.3/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.3/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..4da8ad1bcc --- /dev/null +++ b/versioned_docs/version-v1.3/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Effectiveness + + diff --git a/versioned_docs/version-v1.3/api/cluster-lock.mdx b/versioned_docs/version-v1.3/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.3/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.3/api/dv-exit.mdx b/versioned_docs/version-v1.3/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.3/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.3/api/metrics.mdx b/versioned_docs/version-v1.3/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.3/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.3/api/owr-information.mdx b/versioned_docs/version-v1.3/api/owr-information.mdx new file mode 100644 index 0000000000..0e20b4892a --- /dev/null +++ b/versioned_docs/version-v1.3/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR + + diff --git a/versioned_docs/version-v1.3/api/state.mdx b/versioned_docs/version-v1.3/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.3/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.3/api/system.mdx b/versioned_docs/version-v1.3/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.3/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.3/api/techne-credentials.mdx b/versioned_docs/version-v1.3/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.3/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.3/api/terms-and-conditions.mdx b/versioned_docs/version-v1.3/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..d5d32a5dba --- /dev/null +++ b/versioned_docs/version-v1.3/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TermsAndConditions + + + + diff --git a/versioned_docs/version-v1.3/api/what-is-this-api.md b/versioned_docs/version-v1.3/api/what-is-this-api.md new file mode 100644 index 0000000000..c1442d38ef --- /dev/null +++ b/versioned_docs/version-v1.3/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://holesky.launchpad.obol.org), a dapp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API will be made more easy for code-only interaction in the coming quarters with the release of the Obol-SDK. + +Read more about Obol and how to use the [launchpad](https://holesky.launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.3/community-and-governance/community/README.md b/versioned_docs/version-v1.3/community-and-governance/community/README.md new file mode 100644 index 0000000000..c8d5f1c1b9 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# community + diff --git a/versioned_docs/version-v1.3/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.3/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..6c09edfaa7 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/community/staking-masters.md @@ -0,0 +1,28 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\ + + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.3/community-and-governance/community/techne.md b/versioned_docs/version-v1.3/community-and-governance/community/techne.md new file mode 100644 index 0000000000..3152eb6b75 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/community/techne.md @@ -0,0 +1,119 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\ + + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. ::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.gg/obolnetwork) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.gg/obol) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.gg/obol) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.3/community-and-governance/contribution/README.md b/versioned_docs/version-v1.3/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..5cff17667a --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# contribution + diff --git a/versioned_docs/version-v1.3/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.3/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +````markdown + ```javascript + console.log(error); + ``` +```` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.3/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.3/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e17d6226af --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +- Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +- Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/README.md b/versioned_docs/version-v1.3/community-and-governance/governance/README.md new file mode 100644 index 0000000000..cbdbbfca53 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# governance + diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/collective.md b/versioned_docs/version-v1.3/community-and-governance/governance/collective.md new file mode 100644 index 0000000000..6c9141976a --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/collective.md @@ -0,0 +1,60 @@ +--- +description: "Obol Collective Overview" +sidebar_label: "Collective Overview" +slug: /community-and-governance/governance/collective +--- + +# Collective Overview + +## Purpose + +The Obol Collective’s governance system has two primary goals: + +1. **Resource allocation.** Allocate resources effectively to support the Collective’s vision and grow the Obol Collective's sustainable value. Long-term vision may sometimes conflict with short-term value creation; thus, governance requires a blend of short-term and long-term thinking to allocate the token treasury and protocol revenue effectively. +2. **Capture resistance.** Governance plays a key role in securing the anti-capture and censorship resistance of the Obol Collective. Governance should: + 1. make it possible for operations to continue over the long term without reliance on any individual entity; + 2. prevent any one entity or small group of entities from being able to control or censor. + +## Overview: The Obol Token House and RAF + +Two houses govern the Obol Collective: the Token House and the Obol RAF. + +In the **Token House,** OBOL Token holders are responsible for submitting, deliberating, and voting on governance proposals using the Governance Portal. Token holders can delegate their OBOL Token voting power to their own address or an eligible third party. Addresses with delegated voting power are called “Delegates”. + +In the **Obol Retroactive Fund (RAF)**, OBOL Token Delegates are responsible for allocating funds within the RAF to projects and teams that provide value to the Obol Collective. + +All OBOL holders and Delegates are expected to exercise their authority responsibly and follow the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. + +![](/img/gitbook/image-51.png) + +## The Security Council + +The Security Council is a committee of multi-sig wallet signers with the power to perform certain emergency actions as delegated to it by the Obol Association. + +The Security Council can execute any software upgrade or perform other emergency actions without delay to respond to a security emergency, should one arise. The Security Council must not use its power to perform Emergency Actions except in a true security emergency, such as a critical vulnerability that could significantly compromise the Obol Collective. + +After taking any Emergency Action, the Security Council must issue a full transparency report (at an appropriate time after the security emergency has passed) explaining what was done and why such action was justified. + +## Administration and Implementation + +In all cases, Obol Collective governance is intended to be carried out in a manner consistent with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. The Obol Association will steward this process as described below, with the goal of increasingly decentralising its role over time. + +The Obol Association, via its governance administrators, will facilitate administration to ensure that anyone may participate thoughtfully in governance. Such administrative services may include: + +* Moderation of governance proposals to ensure they are validly submitted and voted upon; +* Removal of proposals that reasonably appear to be fraudulent, spam-oriented, defamatory, hateful, or otherwise inappropriate or inconsistent with the values of the Collective; +* Monitoring of votes, voting power, the votable token supply, and voting periods for purposes of determining whether quorums and approval thresholds are met or accurately reflected; +* Management of mutually contradictory or duplicate proposals that are submitted simultaneously or close to one another; +* Maintenance of the Governance & RAF Portal; +* Other tasks that the Obol Association deems appropriate in connection with the above. + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal or chosen RAF recipients, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails, coupled with an explanation. + +## Vision for Fully On-Chain Governance + +Once Collective’s governance develops and is deemed as sufficiently mature by the Obol Association, the implementations of passed proposals will follow full on-chain execution, where possible. Instead of the Collective’s reliance on the Obol Association for implementation, passed proposals will be moved to a queue to prepare for execution. The queue action will send the proposal to a Timelock contract, which starts a countdown until the proposal can be executed. + +Executing a proposal will run its function calls on-chain. Each proposal can be associated with one or more function calls. These calls will perform actions such as transferring assets from the treasury, updating the Governor's parameters, or calling another smart contract. diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/delegate-guide.md b/versioned_docs/version-v1.3/community-and-governance/governance/delegate-guide.md new file mode 100644 index 0000000000..8a249b10f6 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/delegate-guide.md @@ -0,0 +1,26 @@ +--- +description: "Delegate Guide" +sidebar_label: "Delegate Guide" +slug: /community-and-governance/governance/delegate-guide +--- + +# Delegate Guide + +## Delegate Rules of Engagement + +This document outlines the expectations, responsibilities, and values that should guide interactions within the Obol Collective governance community, including the Obol Forum, Discord, and working group meetings. This Code of Conduct will be reviewed periodically to incorporate feedback and adapt to governance needs. Any changes require community approval through the governance process. + +Please review these principles carefully to ensure alignment with the Obol Collective’s vision and commitment to a decentralized and sustainable ecosystem. + +Please read the rules of engagement on the forum [here](https://community.obol.org/t/delegates-rules-of-engagement/206). + +## **Governance Toolkit** + +These tools or their uses may change over time as governance evolves. For example, additional user interfaces dedicated to governance may be developed. Likewise, while voting currently takes place on-chain through the Governance Contract, some successful votes are administered and implemented by the Obol Association, which should not be the case indefinitely. + +Please see the toolkit on the forum [here](https://community.obol.org/t/governance-toolkit/207). + +## Delegates’ Role in the RAF +The role of Delegates in the RAF is to allocate votes to projects that have made substantial positive impact on the Obol Collective’s Decentralized Operator Ecosystem. Vote allocation is proportional to the Delegates’ delegated power. To determine the funding amounts, the [quadratic funding](https://qf.gitcoin.co/) mechanism is used, to ensure a balanced and equitable distribution of influence. + +Visit read [the delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) on the forum. \ No newline at end of file diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/README.md b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/README.md new file mode 100644 index 0000000000..07404cb5f5 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/README.md @@ -0,0 +1,75 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/governance/grants-program +--- + +# Grants Program + +## **Purpose** + +The Obol Grants Program aims to support projects that advance the strategic goals of the Obol Collective by providing milestone-based funding to builders, educators, and contributors working on public goods aligned with the Distributed Validator (DV) ecosystem. + +This program is specifically designed to address the execution of the strategic SQUAD Goals outlined in [OIP-3](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/) that require community involvement. Each grant proposal must clearly align with **one of the grant tracks**, which reflect these goals. The grant tracks help ensure that funds are directed toward work that directly contributes to the Obol Collective's mission. + +To ensure proposals are aligned with these objectives, each track has a dedicated sub-page with: + +* A self-assessment checklist to help determine if the proposal is in scope +* Guidance on the types of contributions and initiatives encouraged +* Detailed evaluation criteria used to assess submissions + +## Structure + +* The program will operate in 8**-week waves**: + * **Application window:** 2 weeks + * **Review & approvals:** 2 weeks + * **Pause to keep track and provide guidance to the new projects**: 4 weeks +* **Milestone-based funding:** Grants are approved as a full proposal, but **funds are released per milestone**, once validated by the committee. Each proposal must define its expected milestones in advance. Applicants will have the opportunity to clearly outline their milestones during the application process. This includes describing the deliverables for each stage of the project and the success criteria for unlocking the next tranche of funding. A step-by-step guide to structuring and submitting milestone-based proposals is provided in a [dedicated sub-page](how-to-create-a-proposal-in-questbook.md). These milestones serve as checkpoints for disbursement and accountability. +* **Grant tracks aligned with** [**OIP-3 SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388)**:** + * [Boosting Obol DV Adoption](grant-track-for-boosting-obol-dv-adoption.md) + * [Establishing OBOL Token’s Role in DeFi & Governance](grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md) + * [Strengthening the Collective: Operators & Community Growth](grant-track-for-strengthening-the-collective-operators-and-community-growth.md) + +> **Funding Disclaimer:**\ +> The OBOL token amount will be calculated based on the USD value of your grant request using the market price of OBOL at the time your proposal is approved. That means the number of tokens may vary depending on the price at the time of approval. + +## Wave #1 Timeline + +
PhaseDatesNotes
Applications OpenMay 14 – Mai 28Anyone can apply during this period
Review & ApprovalMai 29 - June 11Committee reviews proposals and approves based on milestone scope.
Publish recap of selected proposals and next steps
Pause & Monitoring June 12 - July 9Publish recap of selected proposals and next steps
+ +## Platform + +The program will be managed via [Questbook](https://questbook.app), with future integrations possible (Tally, etc). All proposals, reviewer activity, and milestone tracking will be transparent and publicly viewable. + +## Review Process + +* **Initial pilot approval committee**: 2 members from the Obol Association (Leo & Toma) +* **Later stages may expand to a formal committee & Tally-based voting** +* Reviews are rubric-based, and public by default within Questbook. These are structured scoring frameworks that help reviewers assess applications consistently across several criteria, such as: + + * Alignment with grant track and SQUAD goal(s) + * Feasibility and clarity of the milestones + * Potential impact and relevance to the Obol ecosystem + * Team capacity and track record + + Each grant track sub-page includes the specific rubric and criteria relevant to that category. + +## Budget + +* All **funding will be disbursed on a milestone basis only** _(see above disclaimer)_ +* Future quarterly or annual grant budgets to be approved by DAO governance +* The first pilot wave (Wave #1) will not specify any max budget. + +## Communication + +* Public recap of each wave will be posted on the Obol Forum + +## Future Upgrades + +* **Governance voting integration** via Tally +* **Expanded grant committee** with delegate participation +* **AI-assisted review workflows** if shown to increase efficiency + +## Transparency + +* The Obol Grants Program is currently hosted under Questbook's **open-source plan** +* All activity will remain publicly accessible through Questbook diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md new file mode 100644 index 0000000000..fb6dc80cdf --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md @@ -0,0 +1,88 @@ +--- +sidebar_label: "Grant Track for Boosting Obol DV Adoption" +slug: /community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption +--- + +# Grant Track for Boosting Obol DV Adoption + +The following guide will provide you with all the info you need to apply for a grant related to **Boosting Obol DV Adoption**. [You can apply directly on Questbook, here.](https://questbook.app/proposal_form/?grantId=6808de63300aee1f224f930a\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share) + +## Is My Proposal In-Scope for This Grant Track? + +This Grant Track seeks **technical integrations**, **infrastructure tooling**, and **adoption-driven initiatives** that accelerate the adoption of Obol DVs — especially in high-stake sectors like Liquid Staking, Restaking, and Community Squads. + +Proposals are **in-scope** if they: + +* Integrate Obol DVs into staking protocols (e.g. Lido v3, Etherfi, Swell, EigenLayer) +* Launch or grow community squads staking with DVs +* Build tools, dashboards, or deployment frameworks that reduce barriers to DV adoption +* Educate or onboard new users and node operators into the Obol ecosystem + +## Grant Track Priorities & Squad Goals + +This Grant Track hosts the following **Squad Goals** that represent Obol community priorities: + +#### **Category A – Deepen DVs penetration into (Re-)Staking Protocols** + +* Details: Integrate Obol DVs as the infrastructure layer of Liquid Staking & Restaking Protocols. Protocols represent about 37.5% of the Ethereum stake according to [Hildobby’s staking data](https://dune.com/hildobby/eth2-staking). Obol DVs currently [represent about 2%](https://obol.org/dashboard) of that stake. Example workstream: Collaborations with top protocols existing and new products (e.g., Lido v3, Etherfi eETH, Swell rswETH). +* Success Metrics: Make Obol DVs 10% of the Protocols Stake share. +* Exemples: + * Integrate Obol DVs into a Liquid Staking or Restaking protocol + * Build SDKs, APIs, or plugins that simplify DV integrations for protocols. + * Deployment scripts, wrapper contracts, REST APIs, infra automation tools + +#### **Category B – Deepen DVs penetration with community squads** + +* Details: Launch more community squads across the globe. Continue building launcher tooling and educational content on DVs to make squad staking easy. Currently Obol community squads run about 15,000 ETH. Example workstream: Programs to assist new node operators in setting up and fund Obol DVs. +* Success Metrics: + 1. 20 new community squads + 2. 25,000 ETH running on Obol DVs. +* Exemples: + * Create launcher tooling or deployment guides to enable squads. + * Run educational campaigns, community events, or node operator bootcamps + * Build dashboards, docs, or user-facing UX that reduces DV friction. + +## Milestone Articulation + +Grants in this track will be disbursed based on **clear, outcome-oriented milestones**, ideally aligned with measurable KPIs. + +Competitive grant requests include **3–5 milestones**, such as: + +* Signed protocol integration commitment +* Live testnet deployment +* Mainnet launch with DV cluster +* Target stake threshold hit (e.g., 1,000 ETH in DVs) +* Community feedback, docs, or case studies + +> 💡 Milestones should include both technical outcomes and adoption-based KPIs. + +## Security & Audit Requirements + +Proposals involving smart contract deployments must: + +* Document contracts clearly in the proposal +* If relevant, undergo audit from a reputable third-party auditor (e.g., Dedaub, ChainSecurity) +* Include audit as a funded milestone +* Complete audit before any mainnet funds are disbursed + +*** + +## What Makes a Strong Grant Request? + +* **Clear Impact**: Shows a measurable path to DV adoption across a protocol, institution, or community +* **Strong Team**: Has relevant experience in staking, infra, or validator tech +* **Ecosystem Fit**: Aligns with Obol's decentralization and resilience mission +* **Detailed Milestones**: Tied to real-world outcomes, not just deliverable completion +* **Sustainable Plan**: Long-term support considered (infra, community, updates) + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Applies To** | **Criteria** | +| ----------------------- | ----------------------- | ----------------------------------------------------------------- | +| DV Adoption Potential | All domains | How directly does this increase stake running on Obol DVs? | +| Technical Feasibility | Protocols, Institutions | Can this be realistically built by this team? | +| Stake Impact Projection | Protocols, Institutions | How much stake could realistically be secured with this proposal? | +| Ecosystem Alignment | All domains | Is this aligned with Obol's decentralization mission? | +| Milestone Clarity | All domains | Are deliverables concrete, verifiable, and meaningful? | +| Team Credibility | All domains | Does the team have relevant background or traction? | + diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md new file mode 100644 index 0000000000..4e02800624 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md @@ -0,0 +1,75 @@ +--- +sidebar_label: "Grant Track for Establishing OBOL Token’s Role in DeFi & Governance" +slug: /community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance +--- + +# Grant Track for Establishing OBOL Token’s Role in DeFi & Governance + +The following guide will provide you with all the info you need to apply for a grant related to Establishing OBOL Token’s Role in DeFi & Governance. [You can apply directly on Questbook, here](https://questbook.app/proposal_form/?grantId=6808df2e9ccae779614de4a6\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share). + +## Is My Grant Request In-Scope for This Grant Track? + +This Grant Track focuses on helping OBOL become a **core asset in Ethereum DeFi and protocol governance**, with emphasis on **TGE unlock success**, **on/off-chain liquidity**, and **DeFi integrations**. + +Your proposal is **in-scope** if it contributes to any of the following: + +* Improving liquidity of OBOL/stOBOL on DEXs and aggregators +* Deploying stOBOL as collateral or governance asset in DeFi protocols +* Developing tools, bridges, dashboards, or data integrations for OBOL +* Enhancing token UX or reputation (e.g. Chainlink oracles, analytics) + +> While the TGE and unlock strategy is centrally executed by the Obol Association, the community is encouraged to support OBOL's DeFi path via proposals, integrations, and partnerships. + +## Grant Track Priorities & Goals + +#### **Category A – Deep Liquidity & Market Presence** + +* Details: Provide ample liquidity so that participants can easily trade in and out of (st)OBOL. This ensures market confidence in the token being able to trade large volumes and sustain swings in price actions without too many negative effects such as slippage. +* Metrics: + * Deploy stOBOL as collateral on one Top 10 TVL DeFi Protocols (e.g. Morpho) +* Exemples: + * Design & deploy a stOBOL liquidity vault on Arrakis, Balancer, or Maverick + * Propose DAO-level liquidity incentives across DeFi venues + * Gauge votes, flywheels, or incentive co-funding with protocols. + * Deploy stOBOL as collateral in a major DeFi protocol + * Morpho, Aave, Compound, or FraxLend. Proposal should outline required steps (audits, onboarding, etc). + * Build integrations, bridges, or tools for token usability + * Token routers, zap tools, multi-chain bridges, UI UX support for using OBOL/stOBOL. + +## Milestone Articulation + +Grants will be disbursed based on **milestone-based funding**, with a focus on **liquidity outcomes**, **integration readiness**, and **community activation**. + +Typical milestones may include: + +* Smart contract deployment (vault, adapter, collateral wrapper) +* Governance proposal submission and/or approval +* Integration live on testnet/mainnet +* Trading volume or liquidity KPIs achieved (e.g. $1M TVL, $500K 30D volume) +* Community feedback incorporated or UI launched + +> Aim to tie final milestones to live integrations or measurable liquidity metrics. + +## Security Requirements + +* Smart contract deployments must be audited or forked from audited sources +* Where necessary, coordinate audits with the Obol Association +* Audit completion must be a milestone for DeFi protocol integrations + +## What Makes a Strong Proposal? + +* **Strategic Fit**: Aligns directly with OBOL’s token vision (see OIP-1 & OIP-2) +* **Credible Team**: Strong DeFi, token, or liquidity experience +* **Tangible Outcomes**: Focus on integrations, liquidity depth, or real utility +* **Governance Aware**: Engages with DAO or DeFi governance in a thoughtful way +* **Long-Term View**: Includes sustainability considerations (e.g. vault maintenance, fee-sharing) + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| --------------------------- | ---------------------------------------------------------------------------- | +| **Team Experience** | Demonstrates ability to execute in DeFi, integrations, or token infra | +| **Impact Potential** | Adds liquidity, unlocks new use cases, or supports long-term token utility | +| **Feasibility** | Proposal is technically and strategically realistic within a 3–6 month scope | +| **Alignment with Strategy** | Advances OBOL as a governance or collateral asset per OIPs & roadmap | +| **Clarity & Milestones** | Milestones are specific, measurable, and adoption-oriented | diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-optimizing-decentralized-governance.md b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-optimizing-decentralized-governance.md new file mode 100644 index 0000000000..6d290757af --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-optimizing-decentralized-governance.md @@ -0,0 +1,84 @@ +--- +description: "The following guide will provide you with all the info you need to apply for a grant related to Optimizing Decentralized Governance. You can apply directly on Questbook, here." +sidebar_label: "Grant Track for Optimizing Decentralized Governance" +slug: /community-and-governance/governance/grants-program/grant-track-for-optimizing-decentralized-governance +--- + +# Grant Track for Optimizing Decentralized Governance + +## Is My Grant Request In-Scope for This Grant Track? + +This Grant Track welcomes proposals that: + +* Incentivize sustained delegate participation in governance +* Develop transparent staking-linked reward systems for delegates and token holders +* Create tooling or frameworks to surface and reward governance activity +* Formalize the implementation of Obol’s grants infrastructure +* Support the execution of SQUAD-aligned grant initiatives + +Proposals are **in-scope** if they strengthen the Obol Collective’s governance through **better tools**, **stronger incentives**, or **more coordinated participation**. + +## Grant Track Priorities & **Goal**s + +This Grant Track hosts the following **Grant** **Requests** that align with the governance roadmap: + +#### **Category A – Sustained Delegate Participation** + +* **Goal A1**: Build an **Active Delegate Dashboard** or “Karma Score” system + + _Goal_: Reward token holders delegating to consistently engaged, high-quality delegates + + _Scope_: Track votes, proposal participation, on-chain/off-chain commentary +* **Goal A2**: Design a **staking reward incentive layer** for active delegates + + _Goal_: Allow delegates to earn a portion of OBOL staking rewards for governance activity + + _Scope_: On-chain logic + UI + tracking +* **Goal A3**: Create a **governance reputation system** + + _Goal_: Assign transparent scoring or reputation based on delegate behavior + + _Inspiration_: Karma, Otterspace, SourceCred, Coordinape + +#### **Category B – Formalizing the Grants Program** + +* **Goal B1**: Implement a milestone-based Grants Program for the Obol Association + + _Goal_: Launch and manage the system that will award and track 5+ grants tied to SQUAD goals + + _Scope_: On-chain or hybrid tracking, payout workflows, reporting dashboards +* **Goal B2**: Build grant selection & feedback tooling for the Obol Collective + + _Goal_: Let community members review, endorse, or comment on grant proposals + + _Scope_: Lightweight DAO-native frontend, Quadratic voting/endorsements optional + +## Milestone Articulation + +Proposals should include **3–5 milestones**, structured around **outcomes** and **governance impact**. Strong proposals may include milestones like: + +* Design specs or mockups published and shared with delegates +* MVP shipped to testnet or DAO-wide demo +* Governance module deployed or integrated +* Delegate onboarding supported with documentation or workshops +* Community endorsement or adoption (on-chain or off-chain) + +> 🛠 Projects involving on-chain rewards, delegate dashboards, or governance contracts should include a milestone for audit or external review, prior to mainnet deployment. + +## What Makes a Strong Proposal? + +* **Problem Alignment**: Addresses a real governance challenge — delegate drop-off, unclear rewards, limited visibility +* **Clear Implementation Plan**: The path to delivery is scoped, timed, and explained +* **Community Fit**: Respects and supports the Obol Collective’s values of openness and resilience +* **Participation-First**: Empowers active contributors, rather than reinforcing centralization +* **Future-Proof**: Designed for long-term utility and open-source reuse + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| ------------------------- | -------------------------------------------------------------------------- | +| **Team Experience** | Has the team built governance tools or DAO infra before? | +| **Impact Potential** | Will this meaningfully improve delegate engagement or community alignment? | +| **Technical Feasibility** | Can this actually be delivered as scoped? | +| **Clarity of Milestones** | Are the steps to success defined and measurable? | +| **Ecosystem Alignment** | Does this proposal strengthen Obol's collective governance mission? | diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md new file mode 100644 index 0000000000..2bcd92913f --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md @@ -0,0 +1,72 @@ +--- +sidebar_label: "Grant Track for Strengthening the Collective: Operators & Community Growth" +slug: /community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth +--- + +# Grant Track for Strengthening the Collective: Operators & Community Growth + +The following guide will provide you with all the info you need to apply for a grant related to Strengthening the Collective: Operators & Community Growth. [You can apply directly on Questbook, here](https://questbook.app/proposal_form/?grantId=6808e08e9ccae779614e2cfe\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share). + +## Is My Proposal In-Scope for This Grant Track? + +This Grant Track funds work that builds **capabilities and coordination** within the Obol ecosystem — especially among distributed validator operators and active Collective members. + +You’re likely in-scope if your proposal: + +* Trains, certifies, or supports DV operators in joining Obol clusters +* Improves the Silver Techne onboarding experience, curriculum, or support +* Builds infrastructure, guides, or dashboards to track operator activity or status + +Whether you’re focused on operator growth, or ecosystem education — we want to hear from you. + +## Grant Track Priorities & **Goal**s + +#### **Category A – Operator Development (Silver Techne)** + +* Details: Train and certify a professional class of operators who can scale networks reliably by running Obol DVs. Currently there is [about 600 Silver Techne credentials](https://etherscan.io/token/0xfdb3986f0c97c3c92af3c318d7d2742d8f7ed8cc). +* Success Metrics: Grow the number of Silver Techne Credentials by 30%. +* Exemples: + * Design or improve training content for Silver Techne + * Docs, videos, interactive workshops, validator testnets + * Build or enhance certification workflows and dashboards + * UX to issue/review credentials, operator leaderboards, cluster-readiness tools + * Regionalize operator onboarding programs + * Language localization, timezone-based support, squad coordination templates + +> These proposals should prioritize transparency, inclusion, and fair access for contributors. + +## Milestone Articulation + +Grants are paid out in **staged milestones** that reflect real-world progress and value delivered to the operator ecosystem or community. + +Examples of strong milestones: + +* Training curriculum published, piloted with 20 new operators +* 50+ new Silver Techne credentials issued (with wallet verification) +* Launch of open project board with real-time community activity + +## Security & Credibility Notes + +Grant Requests that touch credentialing, access controls, or public dashboards must: + +* Respect contributor privacy and security +* Be reviewed by at least one Collective contributor for community fit +* Prioritize open-source and reproducible tooling wherever possible + +## What Makes a Strong Grant Request? + +* **Community Fit**: Proposal aligns with Obol’s mission of decentralization and collective stewardship +* **Operator Support**: Drives real growth in the Silver Techne operator pool or quality of operator experiences +* **Transparency**: Proposes open processes, accessible documentation, and easy participation +* **Sustainability**: Suggests systems that can scale or run with community ownership +* **Clear Value**: Tied to quantifiable growth in contributions, certifications, or community activity + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| ------------------------- | -------------------------------------------------------------------------------- | +| **Team Experience** | Is the team familiar with validator ops, contributor tools, or community design? | +| **Impact Potential** | Will this grow or support long-term contributor or operator engagement? | +| **Technical Feasibility** | Is the proposal scoped realistically and implementable with the given resources? | +| **Milestone Clarity** | Are there measurable indicators of success and clear timelines for each phase? | + diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md new file mode 100644 index 0000000000..32d95b7352 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md @@ -0,0 +1,90 @@ +--- +sidebar_label: "How to create a proposal in Questbook?" +slug: /community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook +--- + +# How to create a proposal in Questbook? + +This guide walks you through the full process of preparing and submitting a grant proposal to the Obol Grants Program using [Questbook](https://questbook.app). + +### 1. Respect the Wave Schedule + +Each grant wave follows a strict timeline. Grant requests must be submitted during the **application window** listed in the [Grants Program page](./). + +> ⚠️ Proposals submitted outside of an open wave window will **not** be considered. + +*** + +### 2. Choose the Right Grant Track + +Your grant request must clearly align with **one of the four main grant tracks**, which are tied to the Obol Collective's SQUAD goals. Each track has its own page with: + +* Scope verification checklist +* Expectations and contribution types +* Evaluation criteria used during review + +_**On each grant track page, you will find the link to apply for that specific track on Questbook.**_ + +👉 Visit the grant track guides linked [here](./#structure). + +*** + +### 3. Prepare to Submit on Questbook + +#### If you don't already have a Questbook account: + +* Go to [https://questbook.app](https://questbook.app) +* Create a new wallet or connect an existing one +* Back up your wallet's private key securely — you will need it to access your account + +*** + +### 4. Create Your Application + +1. Select the grant **track** aligned with your grant request and follow the link provided in the dedicated subpage +2. Complete each section of the form, including: + * Project summary + * Team & track record + * Grant track alignment + * Milestones & timelines + * Requested funding & deliverables per milestone + +Each section is pre-structured to guide you in providing the expected information. + +*** + +### 5. Include Your Cost Breakdown + +You must attach a cost breakdown using the **template provided by the Obol Association** (linked below). + +* You may modify the structure, add/remove rows, or use your own format if clearly structured. +* Make sure costs are tied to **milestones**, not just a lump sum. + +👉 [Download the cost breakdown template here](https://docs.google.com/spreadsheets/d/10QoterGwLTZyeCf8yShOuGOaLybJd23qrzHnd28J7AM/edit?usp=sharing) + +*** + +### 6. Post in the Forum + +Once your application is submitted on Questbook: + +* Go to the [**Obol Grants Forum Thread**](https://community.obol.org/t/obol-grants-wave-1-submissions-thread/525) +* Post a comment with: + * Your project name + * A short summary + * A link to your Questbook grant request + +This ensures community visibility and transparency. + +*** + +### 7. What Happens Next + +* During the review period (after the wave closes), your grant request will be evaluated by the current committee. +* Reviews will use the rubric published in your track’s page to evaluate your request. +* Feedback may be shared on Questbook or through the forum. + +**If approved:** + +* You’ll be contacted for milestone validation and next steps for funding. +* Disbursements will occur **after milestone delivery is validated.** diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/obol-token.md b/versioned_docs/version-v1.3/community-and-governance/governance/obol-token.md new file mode 100644 index 0000000000..676da65ba4 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/obol-token.md @@ -0,0 +1,74 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/governance/obol-token +--- + +# The OBOL Token + +The OBOL Token is central to the governance and operation of the Obol Collective. It serves multiple purposes that are essential to its functioning. + +**OBOL Token Transferability:** With the approval of[ OIP-2](https://community.obol.org/t/oip-2-unlock-obol-token/317/30), the OBOL Token is set for a strategic and well-planned unlock. The tokens will be unlocked on the 7th May 2025 at 11:00 UTC, following the completion of centralized exchange listings. Please go to [claim.obol.org](https://claim.obol.org) to unlock airdrop tokens. + +## Token Utility + +### **Governance** + +OBOL Token holders delegate their voting power to delegates who participate in the Token House decision-making processes. This includes voting on proposals affecting the Obol Collective’s direction, upgrades, and funding allocations. Read more about the Token House [here](token-house.md). + +### **Obol Retroactive Funding (RAF)** + +Token holders delegate their voting power to Delegates, who vote on the projects eligible for retroactive funding. Read more about the Obol RAF [here](raf.md). + +### **OBOL Token Staking** + +As per[ OIP-1](https://community.obol.org/t/oip-1-building-and-enabling-staking-for-the-obol-token/312), OBOL token holders will have the opportunity to stake their tokens, contributing to the security and stability of the Collective by preserving governance while earning rewards and being able to engage in DeFi. Staking involves depositing OBOL tokens in a vault (without lockup) that automatically delegates the Tokens if not done already. In return, stakers receive stOBOL, which automatically accrues OBOL Tokens as rewards as it's price vs OBOL increases. + +This staking program will be implemented in phases, allowing the community to gradually engage in and benefit from the system while reinforcing the decentralization of the Obol Collective. For the first six months, the total rewards will be 0.33% of the total supply, providing early participants with attractive rewards. After this period, the staking rewards may be adjusted based on governance proposals and market conditions. This structured rollout ensures a sustainable and rewarding staking experience while reinforcing the decentralization of the Obol Collective. + +### **DeFi** + +Plans are in place to launch several DeFi avenues for the OBOL Token post-TGE, such as liquidity pools, lending protocols (e.g. Morpho) and restaking (e.g. Eigenlayer, Symbiotic). + +### **More Utility Coming Soon** + +Via Token House governance proposals in the [Governance Forum](https://community.obol.org/), the Obol community can add more functionality and utility to the OBOL Token. + +## Token Contract + +The official token contract address of the OBOL Token is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7). + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](https://docs.obol.org/community-and-governance/governance/raf)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/raf.md b/versioned_docs/version-v1.3/community-and-governance/governance/raf.md new file mode 100644 index 0000000000..02ceded9f0 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/raf.md @@ -0,0 +1,73 @@ +--- +description: "The RAF" +sidebar_label: "The RAF" +slug: /community-and-governance/governance/raf +--- + +# The RAF + +Obol’s Retroactive Funding (RAF) mechanism is designed to strengthen and promote the decentralisation of Ethereum's settlement layer by rewarding projects that add value and drive impact for Ethereum’s decentralisation. Read more about the Obol RAF [here](https://blog.obol.org/1-percent-for-decentralisation/). + +Voting and funding distributions occur over a series of **Obol Retroactive Fund (RAF)** rounds, with OBOL token Delegates determining how funds from the RAF are allocated. The first RAF round will open in February 2025. + +## Overview of the Obol RAF: + +* Any project that meets the RAF round’s criteria can make an application. +* OBOL Token Delegates vote on applications proportional to their delegated power and using [quadratic funding](https://qf.gitcoin.co/). +* The Obol RAF rounds occur at intervals and include phases for scoping, application creation, application review, voting, and funding distribution. +* The Obol Association will collect information from projects to distribute grants, including KYC, where required. + +Below is described the steps within each RAF round. Each step takes approximately one week.\ + + +![](/img/gitbook/image-53.png) + +### Step 1: Scoping + +The scope of the round’s impact and the amount of funding to be allocated is defined by the Obol Association at the outset of the round and posted on the Obol Forum. + +### Step 2: Application Registration + +Projects are invited to create an application on the [RAF App](http://raf.obol.org/). Any project or team can apply, but in the future, governance may decide that an application needs to be made by someone holding a minimum amount of OBOL tokens. + +Once a RAF round is opened, to apply for the Obol RAF, projects can create an application on [raf.obol.org](http://raf.obol.org/) by following these steps: + +1. **Create an Application:** Fill out the application form using the [RAF App](http://raf.obol.org/). +2. **Describe Impact:** Specify the category of the project and its impact. + +### Step 3: Application Review + +A subset of OBOL Delegates appointed by the Obol Association reviews applications to ensure compliance with the application rules. + +The Obol Association will also review applications to filter out spam or applications that do not align with the mission of the Obol Collective. + +### Step 4: Voting + +OBOL Delegates vote on projects in proportion to their voting power. Here’s how it works: + +1. **Eligibility:** Every address that has been delegated voting power by OBOL Token holders can submit votes. +2. **Voting Process:** Delegates vote using the [raf.obol.org](http://raf.obol.org) app. Depending on the type of application being reviewed, a specific set of criteria should be used to judge a project's contributions to the Obol Collective. + +:::warning +The Obol Association will monitor votes to ensure contributors are not voting for projects they are directly involved in or where a substantial conflict of interest may be present. Delegates are expected to act in accordance with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. +::: + +### Step 5: Tallying Results + +The voting power of each OBOL Token Delegate is proportional to the amount of OBOL tokens delegated to them. However, the funding results are calculated using [quadratic funding](https://qf.gitcoin.co/), meaning that the square root of the votes is used to determine the final allocation. This approach ensures a broader distribution of funding across the Obol Collective, rather than allowing a small number of winners to dominate. + +### Step 6: Compliance + +The Obol Association will review the list of selected projects, adjust if necessary and collect information from them to distribute the grant legally compliantly (including completing KYC if required). + +### Step 7: Funding distribution + +The overall reward amount for the round is divided among the winning projects based on the delegates' vote and allocation according to the quadratic funding mechanism. + +### **Step 8: Community retrospective** + +After each round, The Obol Association will conduct a retrospective and gather community feedback. + +## Guides for each Round + +RAF1: see the [RAF1 guide](https://community.obol.org/t/guide-for-raf-round-1-raf1/227) in the forum. diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/raf1-guide.md b/versioned_docs/version-v1.3/community-and-governance/governance/raf1-guide.md new file mode 100644 index 0000000000..535f4535cb --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/raf1-guide.md @@ -0,0 +1,37 @@ +--- +description: "RAF1 Guide" +sidebar_label: "RAF1 Guide" +slug: /community-and-governance/governance/raf1-guide +--- + +# RAF1 Guide + +Welcome to the first iteration of the Retroactive Funding (RAF) program by the Obol Collective! By focusing on public goods infrastructure, we aim to strengthen and promote the Obol Collective’s Decentralized Operator Ecosystem and its ability to scale decentralized infrastructure networks like Ethereum. + +The RAF’s first round takes place in Q1 of 2025. RAF1 will allocate 1M OBOL to reward projects dedicated to strengthening and promoting the Obol Collective’s Decentralized Operator Ecosystem. + +Are you a person/entity who wants to apply for RAF1? Read our [RAF1 application guide](https://community.obol.org/t/application-guidelines-raf1/228). + +Are you a Delegate in RAF1? Read our [RAF1 delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229). + +### Overview and Timeline of the Obol RAF1 + +1. **Project Applications (Feb 3 → Feb 10)**\ + Any project within the scope of the round can participate in this round via Obol [RAF app](http://raf.obol.org/). We suggest that projects read the [Application Guidelines](https://community.obol.org/t/application-guidelines-raf1/228) before applying. +2. **Application Review Process (Feb 6 → Feb 10)**\ + The Obol Association will review submissions for spam and fraud. +3. **Voting (Feb 10 → Feb 17)**\ + Delegates are provided with a [RAF1 delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) for RAF1 and asked to vote via the Obol [RAF app](http://raf.obol.org/). +4. **Results, KYC, and Grant Delivery (Feb 17 → Mar 21)**\ + The Association will announce all the selected projects and their funding allocations. RAF recipients must complete a KYC process with the Obol Association. + +## Impact Metrics - Funding allocation design + +The Obol Collective has implemented **impact metrics-based evaluation** to ensure more informed decision-making during funding rounds. These metrics aim to provide delegates with objective data to assess the impact of each project, enabling them to allocate their votes effectively and in alignment with the Collective’s mission. + +* For projects or individuals that increased accessibility, participation, or value within the Obol Decentralized Operator ecosystem, impact metrics include: + * Staked assets: An increase in staked ETH using the project’s tools or services. (Either running on distributed validators, or more generally.) + * User growth: Number of new users using the project’s tools or services (e.g. stakers or operators). +* For projects or individuals which contributed to the development or improvement of open-source tools, protocols, or systems, their impact metrics include: + * Number of lines of code or pull requests merged into relevant repositories. + * Number of bugs fixed, features implemented, or technical improvements made. diff --git a/versioned_docs/version-v1.3/community-and-governance/governance/token-house.md b/versioned_docs/version-v1.3/community-and-governance/governance/token-house.md new file mode 100644 index 0000000000..ed04513eb3 --- /dev/null +++ b/versioned_docs/version-v1.3/community-and-governance/governance/token-house.md @@ -0,0 +1,104 @@ +--- +description: "The Token House" +sidebar_label: "The Token House" +slug: /community-and-governance/governance/token-house +--- + +# The Token House + +In the Token House, OBOL Token holders are responsible for submitting, deliberating, and voting on various Obol Collective governance proposals. + +## Overview of the Obol Token House + +* Proposals are reviewed and voted on in three-week cycles. +* In the first week, anyone may draft a proposal of any type based on [this template](https://community.obol.org/t/proposal-template/208) and post it on the [Forum](https://community.obol.org/) with \[Draft] in the title. Delegates, Obol Collective members, and the general public can provide feedback on proposals in the forum, which should be incorporated into the proposal using the author’s best judgment. +* Once your proposal has been approved by four top-100 Delegates (by voting power), add a link to your proposal to the Voting Cycle Roundup forum thread by the last day of Week 2, and update the title from \[Draft] to \[Final]. The proposal then moves on to Week 3: Voting. +* If your proposal is passed, the Obol Association will facilitate its administration, including distributing approved OBOL Tokens grants. +* If your proposal fails, you can make a new proposal in the next cycle, specifying how you have incorporated significant changes from your first proposal.\\ + + ![](/img/gitbook/Token_house.png) + +## Token House Governance Proposal Process + +Anyone can submit a proposal to the Token House by using the Governance Portal. Proposals are accepted or rejected using a voting process. A proposal must be one of the valid proposal types listed below and follow the voting process described here. + +All governance proposals go through a 3-week cycle. Each “week” runs from Thursday at 7:00 pm GMT until Wednesday at 7:00 pm GMT. + +### Valid Proposal Types + +All governance proposals must fall within one of the following categories: + +* Ecosystem grants +* Protocol upgrades +* Token inflation adjustment +* Treasury allocations +* Work agreements +* Veto on the Obol RAF operations + +The different requirements for submission and approval of each Proposal Type are summarized below. If a specific template is not specified below, proposals should follow this standard proposal template. + +All Ecosystem grant applications are processed by the Association. + +Below are listed types of Token House Proposals. Each has a two-week review period plus one week voting window, with an approval threshold of 51%. + +| Proposal Type | Description | Submission Requirements | +| :-----------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------- | +| Ecosystem grants | The Obol Association’s treasury may be used to support development of the Collective and/or growth of the ecosystem via the proposal template. | Forum proposal + On-Chain Voting | +| Token inflation adjustment | Changes to the OBOL Token Contract or its supply. | Forum proposal + On-Chain Voting | +| Treasury Appropriations | The amount of OBOL Tokens the Obol Association may spend or distribute annually | Proposal initiated by the Association + On-Chain Voting | +| Work agreements | Formal arrangements between the Obol Association and contributors, teams, or organizations tasked with advancing specific initiatives or responsibilities within the ecosystem | Forum proposal + On-Chain Voting | +| Veto on the Obol RAF operations | The veto mechanism serves as a safeguard against decisions or actions within the RAF operations that are misaligned with the mission of decentralization, transparency, or the collective interests of the community. | Forum proposal + On-Chain Voting | +| Protocol upgrades | Scheduled changes to the on-chain smart contracts comprising the protocol or governance contracts. | Forum proposal + On-Chain Voting | +| SQUAD Goals | It reflects the aim of establishing shared, strategic, and community-driven objectives. Goals are set annually, with each cycle beginning in April. | Forum proposal + On-Chain Voting | + +### Weeks 1-2: Feedback and Review + +All proposal types should be posted to the [Obol Forum](https://community.obol.org/) for review. Proposal authors are expected to respond to feedback from Obol Collective members and Delegates. + +Proposals should be: + +* Submitted as a new discussion thread on the [Governance Forum](http://community.obol.tech/) in the appropriate Proposal Category. +* Marked with \[Draft] in the title. +* Formatted and contain information consistent with the [standard proposal template](https://community.obol.org/t/proposal-template/208). + +Before the end of Week 2, a governance administrator will create a Voting Cycle Roundup thread in the forum summarising all the proposals that meet the voting requirements for Week 3 Voting. + +For proposals to proceed to Week 3, four of the top 100 delegates by voting power must give explicit approval on the discussion thread. Delegates may signal approval by pasting the following comment on the proposal discussion thread: _”I am an Obol Delegate \[link to your delegate commitment in your Tally profile] with sufficient voting power, and I believe this proposal is ready to move to a vote."_ + +If a Delegate approves a proposal to move to a vote, it does not endorse that proposal. It simply signifies that they believe the proposal is ready to move to a vote. + +After receiving the required approvals, the author should update the proposal title from \[Draft] to \[Final] and add a link to their proposal in the Voting Cycle Roundup thread by the last day of Week 2 at 19:00 GMT. Authors should also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal’s progress. Proposal authors should include relevant links if feedback was gathered outside the Forum (e.g., on Discord). + +If a proposal author does not get explicit approval or wants more time for feedback, they should not include their proposal in the Voting Cycle Roundup thread. Instead, they should continue to seek community feedback and submit an updated proposal in the next voting cycle. + +### Week 3: Publish a Proposal Onchain and Voting + +During Week 3, a wallet holding at least [30,000 OBOL in voting power](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c#readContract) must publish the proposal on the [Obol Governance Platform](https://www.tally.xyz/gov/obol).\ +After publication, there is a 24-hour voting delay, during which the proposal can be canceled if necessary. The voting delay is the amount of time between when a proposal is submitted and when it goes up for voting. The delay gives token holders time to delegate their voting power before the vote starts or buy more votes. Governor takes a snapshot of all the voting power at the start of voting. Read more [here](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/how-to-pick-governor-parameters#how-to-pick-the-voting-delay). + +\ +After the 24 hours, Delegates (including OBOL Token holders who have self-delegated) vote on proposals via the [Obol Governance Portal](https://vote.obol.org/). All proposals are included in voting if they were added to the Voting Cycle Roundup thread before the deadline and have the approval of four top-100 delegates. + +A governance proposal is **approved** if it satisfies two requirements: + +* **Quorum:** A minimum number of OBOL Token votes measured as _a % of the total votable OBOL Token supply, as of the start of the voting period._ “Votable supply” is the total amount of OBOL Tokens that have been delegated (including to oneself) and, therefore, can participate in voting. The current definition for the OBOL Token House is 0.84% of minted supply. +* **Approval threshold:** The minimum _% of votes cast in support relative to the total number of votes._ The current definition for the OBOL Token House is 0.01% of minted supply. + +A snapshot is taken at the start of each voting period to determine each delegate’s voting power. Voting is hosted on the Obol Governance Portal. + +If a proposal is submitted for a vote and does not pass, the proposal will not be executed. If a proposal author wishes to iterate on a rejected proposal, they should: + +1. Create a new proposal thread on the Forum. +2. Include a link to the first proposal that did not pass. +3. Clearly identify what has changed in the new proposal. + +### Timelock Delay + +After the voting period ends, if the proposal passes, there will be a 5-day timelock delay. The timelock delay is the minimum time required between the approval and execution of a proposal. This delay gives stakeholders a final opportunity to review and react before the proposal is implemented. Read more [here](token-house.md#implementation). + +## Implementation + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails. diff --git a/versioned_docs/version-v1.3/learn/charon/README.md b/versioned_docs/version-v1.3/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.3/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.3/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.3/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..fff5ea1ab4 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/charon/charon-cli-reference.md @@ -0,0 +1,704 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.3.3`](https://github.com/ObolNetwork/charon/releases/tag/v1.3.3). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to exactly 32ETH. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, holesky, gnosis, chiado. + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to exactly 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost (default "default") + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH staked for each). (default 1) + --operator-enrs strings [REQUIRED] Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 30s) + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 1m0s) +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + -h, --help Help for run + --jaeger-address string Listening address for jaeger tracing. + --jaeger-service string Service name used for jaeger tracing. (default "charon") + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its valdiator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 162304) + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 162304) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default ".charon/cluster") + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Test subcommands provide test suite to evaluate current cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [DirectConn Ping PingMeasure PingLoad Libp2pTCPPortOpen PingMeasureRelay PingRelay Ping PingLoad Simulate500 Simulate1000 SimulateCustom PingMeasure Version Synced PeerCount Simulate1 Simulate10 Simulate100 Ping PingMeasure PingLoad Ping PingMeasure CreateBlock DiskWriteSpeed DiskReadSpeed AvailableMemory TotalMemory InternetLatency InternetDownloadSpeed InternetUploadSpeed DiskWriteIOPS DiskReadIOPS] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping Version PingLoad Simulate100 Simulate500 PingMeasure Synced PeerCount Simulate1 Simulate10 Simulate1000 SimulateCustom] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [DiskReadIOPS InternetLatency InternetDownloadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadSpeed AvailableMemory TotalMemory InternetUploadSpeed] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure CreateBlock] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [PingMeasure PingLoad DirectConn Ping Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.3/learn/charon/charon-networking.md b/versioned_docs/version-v1.3/learn/charon/charon-networking.md new file mode 100644 index 0000000000..acf16157fe --- /dev/null +++ b/versioned_docs/version-v1.3/learn/charon/charon-networking.md @@ -0,0 +1,83 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview[​](https://docs.obol.org/learn/charon/networking#overview) {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](https://docs.obol.org/learn/charon/networking#internal-validator-stack) and the [_external p2p network_](https://docs.obol.org/learn/charon/networking#external-p2p-network). + +### Internal Validator Stack[​](https://docs.obol.org/learn/charon/networking#internal-validator-stack) {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network[​](https://docs.obol.org/learn/charon/networking#external-p2p-network) {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](https://docs.obol.org/learn/charon/charon-cli-reference): + +* `--p2p-tcp-addresses`: Addresses for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security[​](https://docs.obol.org/learn/charon/networking#libp2p-authentication-and-security) {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](https://docs.obol.org/learn/charon/cluster-configuration#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p’s Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery[​](https://docs.obol.org/learn/charon/networking#libp2p-relays-and-peer-discovery) {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\ + + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters[​](https://docs.obol.org/learn/charon/networking#scalable-relay-clusters) {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URls. diff --git a/versioned_docs/version-v1.3/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.3/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..babea8e6e0 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralized backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long term decentralization of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definiition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.3/learn/charon/dkg.md b/versioned_docs/version-v1.3/learn/charon/dkg.md new file mode 100644 index 0000000000..6024f9a93e --- /dev/null +++ b/versioned_docs/version-v1.3/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENRs nonce and resign with the clients private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participants old keys out of a distributed validator in favor of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.3/learn/charon/intro.md b/versioned_docs/version-v1.3/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.3/learn/further-reading/README.md b/versioned_docs/version-v1.3/learn/further-reading/README.md new file mode 100644 index 0000000000..6f13128d79 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/further-reading/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading + diff --git a/versioned_docs/version-v1.3/learn/further-reading/community-testing.md b/versioned_docs/version-v1.3/learn/further-reading/community-testing.md new file mode 100644 index 0000000000..91ebf1cfde --- /dev/null +++ b/versioned_docs/version-v1.3/learn/further-reading/community-testing.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community Testing" +slug: /learn/further-reading/community-testing +--- + +# Community Testing + diff --git a/versioned_docs/version-v1.3/learn/further-reading/ethereum-and-its-relationship-with-dvt.md b/versioned_docs/version-v1.3/learn/further-reading/ethereum-and-its-relationship-with-dvt.md new file mode 100644 index 0000000000..52001d8401 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/further-reading/ethereum-and-its-relationship-with-dvt.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum-and-its-relationship-with-dvt +--- + +# Ethereum and Its Relationship With DVT + diff --git a/versioned_docs/version-v1.3/learn/further-reading/peer-score.md b/versioned_docs/version-v1.3/learn/further-reading/peer-score.md new file mode 100644 index 0000000000..7d232ebfa1 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/further-reading/peer-score.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer-score +--- + +# Peer Score + diff --git a/versioned_docs/version-v1.3/learn/further-reading/useful-links.md b/versioned_docs/version-v1.3/learn/further-reading/useful-links.md new file mode 100644 index 0000000000..627e249966 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/further-reading/useful-links.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Useful Links" +slug: /learn/further-reading/useful-links +--- + +# Useful Links + diff --git a/versioned_docs/version-v1.3/learn/futher-reading/README.md b/versioned_docs/version-v1.3/learn/futher-reading/README.md new file mode 100644 index 0000000000..09911677f3 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/futher-reading/README.md @@ -0,0 +1,8 @@ +--- +sidebar_label: "Futher Reading" +slug: /learn/futher-reading/futher-reading +unlisted: true +--- + +# Futher Reading + diff --git a/versioned_docs/version-v1.3/learn/futher-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.3/learn/futher-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..577e2b0347 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/futher-reading/ethereum_and_dvt.md @@ -0,0 +1,56 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/futher-reading/ethereum_and_dvt +unlisted: true +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.3/learn/futher-reading/peer_score.md b/versioned_docs/version-v1.3/learn/futher-reading/peer_score.md new file mode 100644 index 0000000000..f7520d399a --- /dev/null +++ b/versioned_docs/version-v1.3/learn/futher-reading/peer_score.md @@ -0,0 +1,49 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/futher-reading/peer_score +unlisted: true +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of a rated network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.3/learn/futher-reading/resources.md b/versioned_docs/version-v1.3/learn/futher-reading/resources.md new file mode 100644 index 0000000000..0a9b60f1c8 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/futher-reading/resources.md @@ -0,0 +1,60 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/futher-reading/resources +unlisted: true +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.3/learn/futher-reading/testnet.md b/versioned_docs/version-v1.3/learn/futher-reading/testnet.md new file mode 100644 index 0000000000..9244762697 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/futher-reading/testnet.md @@ -0,0 +1,191 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/futher-reading/testnet +unlisted: true +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.3/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.3/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..4b91f85de6 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/introduction/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General[​](https://docs.obol.org/learn/intro/faq#general) {#general} +#### Does Obol have a token?[​](https://docs.obol.org/learn/intro/faq#does-obol-have-a-token) {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/governance/obol-token.md) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is 0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7. + +#### Where can I learn more about Distributed Validators?[​](https://docs.obol.org/learn/intro/faq#where-can-i-learn-more-about-distributed-validators) {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from?[​](https://docs.obol.org/learn/intro/faq#where-does-the-name-charon-come-from) {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node?[​](https://docs.obol.org/learn/intro/faq#what-are-the-hardware-requirements-for-running-a-charon-node) {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster?[​](https://docs.obol.org/learn/intro/faq#what-is-the-difference-between-a-node-a-validator-and-a-cluster) {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine?[​](https://docs.obol.org/learn/intro/faq#can-i-migrate-an-existing-charon-node-to-a-new-machine) {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation[​](https://docs.obol.org/learn/intro/faq#distributed-key-generation) {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator?[​](https://docs.obol.org/learn/intro/faq#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator) {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum numbers of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-threshold). + +### Obol Splits[​](https://docs.obol.org/learn/intro/faq#obol-splits) {#obol-splits} +#### What are Obol Splits?[​](https://docs.obol.org/learn/intro/faq#what-are-obol-splits) {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in future a number of other LSPs. + +#### Are Obol Splits non-custodial?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-non-custodial) {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split?[​](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split) {#can-i-change-the-percentages-in-a-split} +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work?[​](https://docs.obol.org/learn/intro/faq#how-do-obol-splits-work) {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](https://docs.obol.org/learn/intro/obol-splits). + +#### Are Obol Splits open source?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-open-source) {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-audited) {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](https://docs.obol.org/adv/security/smart_contract_audit). + +#### Are the Obol Splits contracts verified on Etherscan?[​](https://docs.obol.org/learn/intro/faq#are-the-obol-splits-contracts-verified-on-etherscan) {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts?[​](https://docs.obol.org/learn/intro/faq#does-my-cold-wallet-have-to-call-the-obol-splits-contracts) {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits?[​](https://docs.obol.org/learn/intro/faq#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits) {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst case mass slashing on the network. Consult the documentation on the contract [here](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient), its audit [here](https://docs.obol.org/adv/security/smart_contract_audit), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs[​](https://docs.obol.org/learn/intro/faq#debugging-errors-in-logs) {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](https://docs.obol.org/adv/troubleshooting/errors). diff --git a/versioned_docs/version-v1.3/learn/intro/key-concepts.md b/versioned_docs/version-v1.3/learn/intro/key-concepts.md new file mode 100644 index 0000000000..9f77ba1c84 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/key-concepts.md @@ -0,0 +1,112 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/introduction/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimizing downtime in mission critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specializes in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof of stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys, that together operate as a threshold key for participating in proof of stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that needs to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 4 | 3/4 | Minimum threshold | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.3/learn/intro/launchpad.md b/versioned_docs/version-v1.3/learn/intro/launchpad.md new file mode 100644 index 0000000000..f2dccb076d --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/launchpad.md @@ -0,0 +1,46 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/introduction/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~** Staking Launchpad**](https://launchpad.ethereum.org/), a public good open source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +| ---------------- | -------------------------------------------------------------------------------- | +| Mainnet | [https://launchpad.obol.org](https://launchpad.obol.org) | +| Gnosis Chain | [https://gnosischain.launchpad.obol.org](https://gnosischain.launchpad.obol.org) | +| Holesky | h[ttps://holesky.launchpad.obol.org](ttps://holesky.launchpad.obol.org) | +| Sepolia | [https://sepolia.launchpad.obol.org](https://sepolia.launchpad.obol.org) | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +## Use the Explorer + +Clicking "explore" on the top right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.3/learn/intro/obol-collective.md b/versioned_docs/version-v1.3/learn/intro/obol-collective.md new file mode 100644 index 0000000000..9073a6460e --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/introduction/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +The Obol Collective is the largest Decentralized Operator Ecosystem. We provides the technology, opportunities, and community to scale decentralized infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs retroactive funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../futher-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](https://docs.obol.org/api), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.3/learn/intro/obol-incentives.md b/versioned_docs/version-v1.3/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..322818cf25 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/obol-incentives.md @@ -0,0 +1,178 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/introduction/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible starting **May 12th, 2025.** + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at anytime but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.gg/obol](https://discord.gg/obol). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | diff --git a/versioned_docs/version-v1.3/learn/intro/obol-splits.md b/versioned_docs/version-v1.3/learn/intro/obol-splits.md new file mode 100644 index 0000000000..e214511264 --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/obol-splits.md @@ -0,0 +1,85 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/introduction/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators. These contracts include: + +* Withdrawal Recipients: Contracts used for a validator's withdrawal address. +* Split contracts: Contracts to split ether across multiple entities. Developed by [Splits.org](https://splits.org/) +* Split controllers: Contracts that can mutate a splitter's configuration. + +Two key goals of validator reward management are: + +1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal+reward_. +2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. + +Without access to the consensus layer state in the EVM to check a validator's status or balance, and due to the incoming ether being from an irregular state transition, neither of these requirements are easily satisfiable. + +The following sections outline different contracts that can be composed to form a solution for one or both goals. The same contracts are being leveraged to enable claiming rewards via launchpad (read more about it [**here**](http://localhost:3000/next/run/running/claim-rewards)). + +### Withdrawal Recipients[​](https://docs.obol.org/learn/intro/obol-splits#withdrawal-recipients) {#withdrawal-recipients} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Withdrawal Recipients focus on the former, receiving the balance skimming from a validator with >32 ether in an ongoing manner, and receiving the principal of the validator upon exit. + +#### Optimistic Withdrawal Recipient[​](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient) {#optimistic-withdrawal-recipient} +![](/img/gitbook/image-15-1-1.png) + +This is the primary withdrawal recipient Obol uses, as it allows for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use an splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + +**OWR Factory Deployment**[**​**](https://docs.obol.org/learn/intro/obol-splits#owr-factory-deployment) + +The OptimisticWithdrawalRecipient contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Goerli | [0xe9557FCC055c89515AE9F3A4B1238575Fcd80c26](https://goerli.etherscan.io/address/0xe9557FCC055c89515AE9F3A4B1238575Fcd80c26) | +| Holesky | [0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df](https://holesky.etherscan.io/address/0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | + +#### Exitable Withdrawal Recipient[​](https://docs.obol.org/learn/intro/obol-splits#exitable-withdrawal-recipient) {#exitable-withdrawal-recipient} +A much awaited feature for proof of stake Ethereum is the ability to trigger the exit of a validator with only the withdrawal address. This is tracked in [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002). Support for this feature will be inheritable in all other withdrawal recipient contracts. This will mitigate the risk to a principal provider of funds being stuck, or a validator being irrecoverably offline. + +### Split Contracts[​](https://docs.obol.org/learn/intro/obol-splits#split-contracts) {#split-contracts} +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers[​](https://docs.obol.org/learn/intro/obol-splits#split-controllers) {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. A permissive controller and a restrictive controller are given as examples below. + +#### (Gnosis) SAFE wallet[​](https://docs.obol.org/learn/intro/obol-splits#gnosis-safe-wallet) {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administrate a mutable split. The most well-known deployment of this pattern is the [protocol guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + +#### Immutable Split Controller[​](https://docs.obol.org/learn/intro/obol-splits#immutable-split-controller) {#immutable-split-controller} +This is a [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/controllers/ImmutableSplitController.sol) that updates one split configuration with another, exactly once. Only a permissioned address can trigger the change. This contract is suitable for changing a split at an unknown point in future to a configuration pre-defined at deployment. + +The Immutable Split Controller [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/controllers/ImmutableSplitControllerFactory.sol) can be found at the following addresses: + +\ + + +| Chain | Address | +| ------- | ---------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x49e7cA187F1E94d9A0d1DFBd6CCCd69Ca17F56a4](https://etherscan.io/address/0x49e7cA187F1E94d9A0d1DFBd6CCCd69Ca17F56a4) | +| Goerli | [0x64a2c4A50B1f46c3e2bF753CFe270ceB18b5e18f](https://goerli.etherscan.io/address/0x64a2c4A50B1f46c3e2bF753CFe270ceB18b5e18f) | +| Holesky | | +| Sepolia | | diff --git a/versioned_docs/version-v1.3/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.3/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..07f1787e8b --- /dev/null +++ b/versioned_docs/version-v1.3/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/introduction/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and PKI + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.3/run-a-dv/integrations/README.md b/versioned_docs/version-v1.3/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..77e5bf9a25 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# integrations + diff --git a/versioned_docs/version-v1.3/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.3/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..b7b9b507a4 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,58 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) and other applications. + +### Pre-requisites[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#pre-requisites) {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](https://docs.obol.org/next/adv/advanced/quickstart-sdk) is required. + +### Create a SAFE to own the EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-safe-to-own-the-eigenpod) {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-an-eigenpod) {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-splitter-for-the-block-reward) {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-the-dv-cluster-invite) {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](https://docs.obol.org/next/run/start/quickstart_group) on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](https://docs.obol.org/next/run/integrations/quickstart-sdk) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#deposit-and-restake-your-distributed-validator) {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. + diff --git a/versioned_docs/version-v1.3/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.3/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..6621ad1364 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/integrations/dappnode.md @@ -0,0 +1,30 @@ +--- +sidebar_label: "DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# DappNode + +For setup, see quickstart guide:[​](https://docs.obol.org/next/run/integrations/Dappnode#for-setup-see-quickstart-guide) + +For setup of a DV using Dappnode, see the quickstart guide [Create a DV Alone](https://docs.obol.org/next/run/start/quickstart_alone), and select the appropriate tab for "Dappnode". + +### Frequently asked questions[​](https://docs.obol.org/next/run/integrations/Dappnode#frequently-asked-questions) {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster?[​](https://docs.obol.org/next/run/integrations/Dappnode#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-the-validator-and-charon-volumes-to-use-the-same-enr-for-another-cluster) {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC?[​](https://docs.obol.org/next/run/integrations/Dappnode#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag-for-lodestar-vc) {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically.\ + + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol?[​](https://docs.obol.org/next/run/integrations/Dappnode#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-same-dappnode-machine-push-monitoring-data-from-both-clusters-to-obol) {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.3/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.3/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..ba6cc919bc --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,226 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://operatorportal.lido.fi/modules/community-staking-module) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from Holesky just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using CSM UI in advanced mode, using the `extendedManagerPermissions` to set the `managerAddress` to the cluster multi-sig (SAFE) and the `rewardAddress` to the Splits.org splitting contract. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (if members want to use a distinct address to the one they sign with for receiving rewards). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (reccommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol’s '[1% for Decentralisation](https://blog.obol.org/1-percent-for-decentralisation/)' Retroactive Fund, thereby earning [Obol Contributions](https://obol.org/contributions) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [retroactivefunding.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol's RAF. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated a CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create up to 12 validator keys (CSM's Early Access limit) with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create (CSM's Early Access phase is capped at a maximum 12 validators). +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using you favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM is launching with a whitelisted set of approved operators (Early Access). The squad member with EA should be the one to create the node through the CSM widget. + +The EA member will head to [CSM Extended Mode](https://csm.lido.fi/?mode=extended) and connect their wallet. (Note the `mode=extended` parameter.) This allows the Lido CSM reward address to be set to the split contract created earlier. + +![](/img/gitbook/image-47.png) + +The EA member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The EA member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The EA member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button.\ + + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.3/run-a-dv/prepare/README.md b/versioned_docs/version-v1.3/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..6d77f77e82 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# prepare + diff --git a/versioned_docs/version-v1.3/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.3/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..09f03f65be --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,99 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10mb/s internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25mb/s internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimize both performance and cost-effectiveness, it is recommended to prioritize physical over virtualized setups. Such configurations typically offer greater performance and minimize overhead associated with virtualization, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimize Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimize potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes would potentially impact the fault tolerance of the cluster and as a result should be avoided. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. Be sure to use encrypted communication between your VC and the Charon client, potentially through a cloud-provided network, a self-managed network tunnel, a VPN, a Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), or other manner. + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration/#cluster-size-and-resilience)). + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](./test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +The clusters should consist of a combination of your preferred consensus, execution, and validator clients. It is recommended to include a combination of multiple clients in order to have a healthy client diversity within the cluster, ideally, if any single client type fails, it should be less than the fault tolerance of the cluster, and the validators should stay online/not do anything slashable. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Metrics Monitoring + +As requested by Obol Labs, node operators can push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. Our recommendation for operators is to independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (usually < 24 hours). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.3/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.3/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..6988ffd3b2 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatability information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.3/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.3/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..ed66d70abd --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,483 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + + + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the beacon node and validator client tests, you need to point them toward the correct Docker container, and also include the Docker container’s network. Check your docker networks with `docker network ls`. When you run the test command, specify the Docker network with `--network `. Read more about docker networking [here](https://docs.docker.com/engine/network/). + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.3.3 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.3.3 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.3.3 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.3.3 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.3.3 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.3.3 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +``` +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +``` +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + +#### Pre-requisites + +The storage tests require `fio` to be installed on your machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +#### Example run + +```sh +charon alpha test infra +``` diff --git a/versioned_docs/version-v1.3/run-a-dv/running/README.md b/versioned_docs/version-v1.3/run-a-dv/running/README.md new file mode 100644 index 0000000000..515e6cbede --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# running + diff --git a/versioned_docs/version-v1.3/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.3/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..3c7cddf6d9 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +Use any of the following tools to deposit. Please use the third-party tools at your own risk and always double check the staking contract address. + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. diff --git a/versioned_docs/version-v1.3/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.3/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..3d4aa06850 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/running/claim-rewards.md @@ -0,0 +1,66 @@ +--- +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +Introduction[​](https://docs.obol.org/next/run/running/claim-rewards#introduction) + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator’s withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +The method for claiming rewards depends on the Cluster's withdrawal configuration, whether it's an [**OWR**](https://docs.obol.org/next/learn/intro/obol-splits#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](https://docs.obol.org/next/learn/intro/obol-splits#exitable-withdrawal-recipient) . The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +\ + + +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](https://docs.obol.org/run/integrations/lido-csm). | + +### Claim Flow[​](https://docs.obol.org/next/run/running/claim-rewards#claim-flow) {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](https://docs.obol.org/next/learn/intro/obol-splits). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +1. All validator rewards are accumulated in the validator's withdrawal address, which is a split wallet. +2. Claims can be triggered in two ways: + 1. **From addresses in the Splitter**: Splitter addresses will see a `Claim All` button. When the first address (e.g., address A) executes `Claim All`, it triggers a multi-call transaction to distribute rewards from all the split wallets associated with a cluster into the Split Main. The Split Main then sends address A’s proportion of the rewards (based on the split configuration at the time of cluster creation). All of this is executed with a single click for the first address. + 2. **From addresses not in the Splitter**: Non-splitter addresses will see a `Distribute All` button instead of `Claim All`. These addresses cannot claim rewards directly but can distribute rewards to the Split Main (subsidizing transaction fees for others). Operators can then claim rewards later by visiting the same cluster details page. +3. Internally, after clicking `Claim All` or `Distribute All`, the split wallet sends the funds to the Split Main contract. +4. The Split Main then sends proportional rewards to **address A**, completing steps 2a, 3, and 4 with a single click. +5. Other addresses (e.g., B, C, D) can later click on `Claim All` to receive their share of the rewards. + +### Launchpad Edge Cases[​](https://docs.obol.org/next/run/running/claim-rewards#launchpad-edge-cases) {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: The `Claimable` column doesn’t match the amount next to the `Claim All` button. {#case-1-the-claimable-column-doesnt-match-the-amount-next-to-the-claim-all-button} +![](/img/gitbook/image-87.png) + +![](/img/gitbook/image-1-1-1-1-1.png) + +In this scenario, someone else (a splitter or non-splitter address) has already distributed rewards to the Split Main (e.g., 0.12 ETH). However, your validators (4 in this case) have earned an additional 0.2 ETH in rewards. Your total effective claimable balance is 0.032 ETH, which you can claim using the `Claim All` button. + +:::info +Your total effective claimable amount will always be displayed next to the `Claim All` button. +::: + +#### Case 2: You don’t see a `Claim All` button but instead see `Distribute All`.[​](https://docs.obol.org/next/run/running/claim-rewards#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all) {#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all} +![](/img/gitbook/image-88.png) + +This happens because the connected address is not listed in the split configuration. You may have used a different operator address from the one in the splitter configuration. You can: + +* Distribute all rewards using the connected address for all operators and claim using your address in the splitter configuration. +* Switch to the splitter address and claim directly. + +Note: It costs the same gas to distribute rewards for one address as it does for all addresses. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows a `Claim All` amount. {#case-3-you-just-created-a-new-cluster-with-no-active-validators-or-rewards-but-it-shows-a-claim-all} +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all `Claim All` buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.3/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.3/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..0d6e1c92fa --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,933 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction[​](https://docs.obol.org/next/run/running/quickstart-exit#introduction) {#introduction} +Users looking to exit staking entirely and withdraw their full balance back must sign and broadcast a "voluntary exit" message with validator keys which will start the process of exiting from staking. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proporiton of principal and rewards. + +There are two ways to sign the partial exit and broadcast the full exit. Both the solutions don't require gas. + +1. **Using the Charon’s exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via launchpad and ability to download partial exits and broadcast them later as required. Users don’t have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use launchpad to monitor exit status and will have to use grafana to query the partial exit status. + +:::info +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +As per your preferences, choose the correct combination of - + +1. **Network** : Mainnet or Holesky +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quanity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +#### Step 1: Submit partial exit {#introduction} + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message.\\ + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](/img/gitbook/spaces_XeyaDcGpivHZJ18c2xxu_uploads_git-blob-9d5df062b767cf6cefe35e34437b25b1a0104f47_image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch[​](https://docs.obol.org/next/run/running/quickstart-exit#exit-epoch-and-withdrawable-epoch) {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.3/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.3/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..ad83244f95 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/running/monitoring.md @@ -0,0 +1,90 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/d6qujIJVk/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show following page. Choose Discord in the `Integration` drop down.\ + + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) . + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.3/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.3/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..c33e9bd637 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,124 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimse liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimse liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + diff --git a/versioned_docs/version-v1.3/run-a-dv/start/README.md b/versioned_docs/version-v1.3/run-a-dv/start/README.md new file mode 100644 index 0000000000..f8e137e70b --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# start + diff --git a/versioned_docs/version-v1.3/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.3/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..ecfbefcb63 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,215 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](https://docs.obol.org/run/start/quickstart_group) instead for this latter case. +::: + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_alone#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.3.3 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 create cluster \ + --nodes=6 \ + --network=holesky \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](https://docs.obol.org/next/run/start/quickstart_alone#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately.\ +\ +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Holesky testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Setup the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample.holesky .env +``` +::: + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.3/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.3/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..89e63f6eff --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,618 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_group#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](https://docs.obol.org/next/run/prepare/deployment-best-practices#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](https://docs.obol.org/next/adv/troubleshooting/errors#docker-permission-denied-error) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client**[**​**](https://docs.obol.org/next/run/start/quickstart_group#prepare-an-execution-and-consensus-client) + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package**[**​**](https://docs.obol.org/next/run/start/quickstart_group#install-the-obol-dappnode-package) + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will be see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge**[**​**](http://localhost:3000/run/start/quickstart_group#installing-sedge) + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful**[**​**](http://localhost:3000/run/start/quickstart_group#check-the-install-was-successful) + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +#### Collect addresses, configure the cluster, share the invitation + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + 1. Select the desired amount of validators (32 ETH each) the cluster will run. (Note that the mainnet launchpad is restricted to one validator for now.) + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr) in the "What is your charon client's ENR?" field. + 3. Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. + 4. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions of participating as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +#### Join the cluster prepared by the creator + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address provided to the leader.\ + + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue.\ + + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr).\\ + + ![](/img/gitbook/image-83.png) +6. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +7. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](https://docs.obol.org/next/learn/charon/dkg) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) \\ + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. \\ + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.3.3 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run.\\ + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page.\\ + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +#### Create a DV Node Backup + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present.\\ + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long term. + + + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose, further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Holesky testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +````sh +# To prepare the node for the Holesky test network +# Copy ".env.sample.holesky", renaming it ".env" +cp .env.sample.holesky .env + + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env + + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```shell + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +```` + +:::warning +Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. +::: + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/d6qujIJVk/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). + + + +To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-generate) + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Holesky network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=holesky --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-import-key) + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ holesky teku +``` + +**Sedge Run**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-run) + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. + + + +Use an ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. + + + +Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. + + + +Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. + + + + + +:::warning +Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. +::: + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Copy the `docker-compose.override.yml.sample` file + +```sh +cp -n docker-compose.override.yml.sample docker-compose.override.yml +``` + +2. Uncomment the `profiles: [disable]` section for both `nethermind` and `lighthouse`. The override file should now look like this + +``` +services: + nethermind: + # Disable nethermind + profiles: [disable] + # Bind nethermind internal ports to host ports + #ports: + #- 8545:8545 # JSON-RPC + #- 8551:8551 # AUTH-RPC + #- 6060:6060 # Metrics + lighthouse: + # Disable lighthouse + profiles: [disable] + # Bind lighthouse internal ports to host ports + #ports: + #- 5052:5052 # HTTP + #- 5054:5054 # Metrics +... +``` + +3. Then, uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +4. Restart your docker compose + +```sh +docker compose down +docker compose up -d +``` + + + +:::tip +In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is `:3610`. Read more about Charon's networking [here](https://docs.obol.org/next/learn/charon/networking). +::: + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](https://docs.obol.org/next/run/running/activate-dv) to begin staking. diff --git a/versioned_docs/version-v1.3/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.3/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..8aa5fff0de --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,56 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics to Obol Monitoring" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics to Obol Monitoring + +:::info +This is **optional** and does not confer any special privileges within the Obol Network. +::: + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](http://localhost:3000/run/start/quickstart_overview), and have been provided with **Monitoring Credentials** used to push distributed validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve your Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +#### Update the monitoring token in the `.env` file + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +#### Save the `.env` file and restart Prometheus + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab.\\ + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it.\\ + + ![](/img/gitbook/image-86.png) + + diff --git a/versioned_docs/version-v1.3/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.3/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..be7af33fc1 --- /dev/null +++ b/versioned_docs/version-v1.3/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to utilize Distributed Validators for solo or multi-operator staking. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](./create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](./create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.3/sdk/classes/Client.md b/versioned_docs/version-v1.3/sdk/classes/Client.md new file mode 100644 index 0000000000..77910867be --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/classes/Client.md @@ -0,0 +1,246 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +### Extends + +* `Base` + +### Constructors + +#### new Client() + +> **new Client**(`config`, `signer`?): [`Client`](Client.md) + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | -------- | --------------------- | +| `config` | `object` | Client configurations | +| `config.baseUrl`? | `string` | obol-api url | +| `config.chainId`? | `number` | Blockchain network ID | +| `signer`? | `Signer` | ethersJS Signer | + +**Returns** + +[`Client`](Client.md) + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client:[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +**Overrides** + +`Base.constructor` + +**Defined in** + +index.ts:66 + +### Methods + +#### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`<`string`> + +Accepts Obol terms and conditions to be able to create or update data. + +**Returns** + +`Promise`<`string`> + +terms and conditions acceptance success message. + +**Throws** + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions:[acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +**Defined in** + +index.ts:79 + +*** + +#### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys OWR and Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| --------------------- | ------------------------------------------------------------- | --------------------------------------- | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit:[createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed\ +and not pushed to version control. + +**Defined in** + +index.ts:133 + +*** + +#### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| ------------------- | ----------------------------------------------------------- | -------------------------------------------------- | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit:[createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed\ +and not pushed to version control. + +**Defined in** + +index.ts:254 + +*** + +#### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`<`string`> + +Creates a cluster definition which contains cluster configuration. + +**Parameters** + +| Parameter | Type | Description | +| ------------ | ----------------------------------------------------- | ----------------------- | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +**Returns** + +`Promise`<`string`> + +config\_hash. + +**Throws** + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition:[createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +**Defined in** + +index.ts:350 + +*** + +#### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Approves joining a cluster with specific configuration. + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition. + +**Throws** + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition:[acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +**Defined in** + +index.ts:415 + +*** + +#### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | ---------------------------------------------------------- | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition for config hash + +**Throws** + +On not found config hash. + +An example of how to use getClusterDefinition:[getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +**Defined in** + +index.ts:469 + +*** + +#### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | -------------------------------------------- | +| `configHash` | `string` | The configuration hash in cluster-definition | + +**Returns** + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +**Throws** + +On not found cluster definition or lock. + +An example of how to use getClusterLock:[getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +**Defined in** + +index.ts:488 diff --git a/versioned_docs/version-v1.3/sdk/classes/README.md b/versioned_docs/version-v1.3/sdk/classes/README.md new file mode 100644 index 0000000000..d71a58615e --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# classes + diff --git a/versioned_docs/version-v1.3/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.3/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..7dda512eb1 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,15 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `0x00000000` | `1` | Mainnet. | types.ts:6 | +| `0x00001020` | `5` | Goerli/Prater. | types.ts:9 | +| `0x00000064` | `100` | Gnosis Chain. | types.ts:12 | +| `0x01017000` | `17000` | Holesky. | types.ts:15 | diff --git a/versioned_docs/version-v1.3/sdk/enumerations/README.md b/versioned_docs/version-v1.3/sdk/enumerations/README.md new file mode 100644 index 0000000000..5069f1f6ed --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# enumerations + diff --git a/versioned_docs/version-v1.3/sdk/functions/README.md b/versioned_docs/version-v1.3/sdk/functions/README.md new file mode 100644 index 0000000000..62be7a3a85 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# functions + diff --git a/versioned_docs/version-v1.3/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.3/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..a8aef00e37 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/functions/validateClusterLock.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock + +> **validateClusterLock**(`lock`): `Promise`<`boolean`> + +Verifies Cluster Lock's validity. + +### Parameters + +| Parameter | Type | Description | +| --------- | ----------------------------------------------- | ------------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | + +### Returns + +`Promise`<`boolean`> + +boolean result to indicate if lock is valid + +### Throws + +on missing keys or values. + +An example of how to use validateClusterLock:[validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) + +### Defined in + +services.ts:13 diff --git a/versioned_docs/version-v1.3/sdk/index.md b/versioned_docs/version-v1.3/sdk/index.md new file mode 100644 index 0000000000..d22906b706 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/index.md @@ -0,0 +1,93 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + +# Intro + +**SDK Version:** v2.1.0 + +![Obol Logo](https://obol.org/obolnetwork.png) + +## Obol SDK + +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](https://docs.obol.org/api). + +### Getting Started + +Checkout our [docs](https://docs.obol.org/advanced/quickstart-sdk), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +### Terms and Conditions + +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +### ⚠️ Important Security Notice: + +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +* The private key is securely stored (e.g., in an `.env` file). +* Never commit or push your `.env` file containing the private key to version control. + +### Contributing + +Please review the following guidelines: + +* [How to Report Bugs](index.md#how-to-report-bugs) +* [How to Propose Changes](index.md#how-to-propose-changes) +* [Code Review Process](index.md#code-review-process) + +#### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +#### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +#### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +### Enumerations + +* [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +### Classes + +* [Client](classes/Client.md) + +### Interfaces + +* [ClusterDefinition](interfaces/ClusterDefinition.md) +* [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) + +### Type Aliases + +* [ClusterOperator](type-aliases/ClusterOperator.md) +* [OperatorPayload](type-aliases/OperatorPayload.md) +* [ClusterCreator](type-aliases/ClusterCreator.md) +* [ClusterValidator](type-aliases/ClusterValidator.md) +* [ClusterPayload](type-aliases/ClusterPayload.md) +* [SplitRecipient](type-aliases/SplitRecipient.md) +* [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +* [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +* [BuilderRegistration](type-aliases/BuilderRegistration.md) +* [DepositData](type-aliases/DepositData.md) +* [DistributedValidator](type-aliases/DistributedValidator.md) +* [ClusterLock](type-aliases/ClusterLock.md) +* [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) + +### Functions + +* [validateClusterLock](functions/validateClusterLock.md) diff --git a/versioned_docs/version-v1.3/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.3/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..b57096a0bf --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +Cluster definition data needed for dkg + +## Extends + +- [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | `ClusterPayload.name` | types.ts:73 | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)[] | The cluster nodes operators addresses. | `ClusterPayload.operators` | types.ts:76 | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)[] | The cluster validators information. | `ClusterPayload.validators` | types.ts:79 | +| `deposit_amounts?` | `null` \| `string`[] | The cluster partial deposits in gwei or 32000000000. | `ClusterPayload.deposit_amounts` | types.ts:82 | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | types.ts:90 | +| `version` | `string` | The cluster configuration version. | - | types.ts:93 | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | types.ts:96 | +| `fork_version` | `string` | The cluster fork version. | - | types.ts:99 | +| `uuid` | `string` | The cluster uuid. | - | types.ts:102 | +| `timestamp` | `string` | The cluster creation timestamp. | - | types.ts:105 | +| `config_hash` | `string` | The cluster configuration hash. | - | types.ts:108 | +| `threshold` | `number` | The distributed validator threshold. | - | types.ts:111 | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | types.ts:114 | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | types.ts:117 | diff --git a/versioned_docs/version-v1.3/sdk/interfaces/README.md b/versioned_docs/version-v1.3/sdk/interfaces/README.md new file mode 100644 index 0000000000..b635dbc6dc --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# interfaces + diff --git a/versioned_docs/version-v1.3/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.3/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..f52df5e475 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +OWR and Split Proxy Params + +## Extends + +- [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | types.ts:136 | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | types.ts:139 | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | types.ts:142 | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | types.ts:145 | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | types.ts:153 | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | types.ts:156 | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | types.ts:159 | diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.3/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..281cd48a13 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +> **BuilderRegistration**: `object` + +Pre-generated Signed Validator Builder Registration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | types.ts:184 | +| `signature` | `string` | BLS signature of the builder registration message. | types.ts:187 | + +## Defined in + +types.ts:182 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.3/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..f7467b4436 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +> **BuilderRegistrationMessage**: `object` + +Unsigned DV Builder Registration Message + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient` | `string` | The DV fee recipient. | types.ts:167 | +| `gas_limit` | `number` | Default is 30000000. | types.ts:170 | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | types.ts:173 | +| `pubkey` | `string` | The public key of the DV. | types.ts:176 | + +## Defined in + +types.ts:165 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..643f98978e --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +> **ClusterCreator**: `object` + +Cluster creator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The creator address. | types.ts:52 | +| `config_signature`? | `string` | The cluster configuration signature. | types.ts:54 | + +## Defined in + +types.ts:50 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..e386f0060e --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +> **ClusterLock**: `object` + +Cluster Details after DKG is complete + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | types.ts:235 | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)[] | The cluster distributed validators. | types.ts:238 | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | types.ts:241 | +| `lock_hash` | `string` | The hash of the cluster lock. | types.ts:244 | +| `node_signatures`? | `string`[] | Node Signature for the lock hash by the node secp256k1 key. | types.ts:247 | + +## Defined in + +types.ts:233 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..c12e7caa48 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +> **ClusterOperator**: `object` + +Node operator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The operator address. | types.ts:23 | +| `enr`? | `string` | The operator ethereum node record. | types.ts:26 | +| `fork_version`? | `string` | The cluster fork_version. | types.ts:29 | +| `version`? | `string` | The cluster version. | types.ts:32 | +| `enr_signature`? | `string` | The operator enr signature. | types.ts:35 | +| `config_signature`? | `string` | The operator configuration signature. | types.ts:38 | + +## Defined in + +types.ts:21 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..ab4d99aff2 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +> **ClusterPayload**: `object` + +Cluster configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | types.ts:73 | +| `operators` | [`ClusterOperator`](ClusterOperator.md)[] | The cluster nodes operators addresses. | types.ts:76 | +| `validators` | [`ClusterValidator`](ClusterValidator.md)[] | The cluster validators information. | types.ts:79 | +| `deposit_amounts`? | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | types.ts:82 | + +## Defined in + +types.ts:71 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..266d48a113 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +> **ClusterValidator**: `object` + +Validator withdrawal configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | types.ts:62 | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | types.ts:65 | + +## Defined in + +types.ts:60 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.3/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..592d2f643b --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +> **DepositData**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | The public key of the distributed validator. | types.ts:195 | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | types.ts:198 | +| `amount` | `string` | 32 ethers. | types.ts:201 | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | types.ts:204 | +| `signature` | `string` | BLS signature of the deposit message. | types.ts:207 | + +## Defined in + +types.ts:193 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.3/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..5ec5dcc09d --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +> **DistributedValidator**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | types.ts:215 | +| `public_shares` | `string`[] | The public key of the node distributed validator share. | types.ts:218 | +| `deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\> | The deposit data for activating the DV. | types.ts:221 | +| `partial_deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\>[] | The deposit data with partial amounts or full amount for activating the DV. | types.ts:224 | +| `builder_registration`? | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | types.ts:227 | + +## Defined in + +types.ts:213 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.3/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..c08cb82c83 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +> **ETH\_ADDRESS**: `string` + +String expected to be Ethereum Address + +## Defined in + +types.ts:253 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.3/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..ee7810452c --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +> **OperatorPayload**: `Partial`\<[`ClusterOperator`](ClusterOperator.md)\> & `Required`\<`Pick`\<[`ClusterOperator`](ClusterOperator.md), `"enr"` \| `"version"`\>\> + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. + +## Defined in + +types.ts:44 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/README.md b/versioned_docs/version-v1.3/sdk/type-aliases/README.md new file mode 100644 index 0000000000..9e1ac60271 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# type-aliases + diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.3/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..e40db01a6c --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +> **SplitRecipient**: `object` + +Split Recipient Keys + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `account` | `string` | The split recipient address. | types.ts:125 | +| `percentAllocation` | `number` | The recipient split. | types.ts:128 | + +## Defined in + +types.ts:123 diff --git a/versioned_docs/version-v1.3/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.3/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..12e45d2c89 --- /dev/null +++ b/versioned_docs/version-v1.3/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +> **TotalSplitPayload**: `object` + +Split Proxy Params + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)[] | The split recipients addresses and splits. | types.ts:136 | +| `ObolRAFSplit`? | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | types.ts:139 | +| `distributorFee`? | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | types.ts:142 | +| `controllerAddress`? | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | types.ts:145 | + +## Defined in + +types.ts:134 diff --git a/versioned_docs/version-v1.3/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.3/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..5368c6e179 --- /dev/null +++ b/versioned_docs/version-v1.3/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# walkthroughs + diff --git a/versioned_docs/version-v1.3/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.3/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.3/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_docs/version-v1.4/README.md b/versioned_docs/version-v1.4/README.md new file mode 100644 index 0000000000..5b583a5d7f --- /dev/null +++ b/versioned_docs/version-v1.4/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Introduction" +slug: /learn/readme +--- + +# Introduction + diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..27650c3586 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# advanced + diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..6b3411b426 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 `tempo`. 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 +``` diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/beacon-node-authentication.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/beacon-node-authentication.md new file mode 100644 index 0000000000..2155b6158e --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/beacon-node-authentication.md @@ -0,0 +1,39 @@ +--- +description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control." +sidebar_label: "Beacon node authentication" +slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication +--- + +# Beacon node authentication + +## HTTP Basic Access Authentication + +If you want to use Charon with a [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic ` where `Authorization`will be the header key and `Basic ` will be the header value. The `` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`. + +:::warning +These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node. +::: + +## Usage example + +Suppose we have a HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command: + +``` +echo -n "john:doe" | base64 +``` + +Then you could pass the flag to your Charon instance like this: + +``` +charon run --beacon-node-headers="Authorization=Basic am9objpkb2U=" +``` + +Or you could specify it as an environment variable like this: + +``` +CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U=" +``` + +:::info +Note that 'Authorization' is followed with an `=` rather than the usual `:`. +::: diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..cb8e916119 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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](https://docs.obol.org/next/learn/intro/launchpad). + +### Pre-requisites[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#pre-requisites) {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#install-the-package) {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#instantiate-the-client) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#propose-the-cluster) {#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. + +```sh +// 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#invite-the-operators-to-complete-the-dkg) {#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](https://docs.obol.org/next/learn/intro/launchpad) to complete the process + +1. Operators navigate to `https://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](https://docs.obol.org/next/run/start/quickstart_group) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#retrieve-the-created-distributed-validators-using-the-sdk) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#activate-the-dvs-using-the-deposit-contract) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#usage-examples) {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/custom-graffiti.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/custom-graffiti.md new file mode 100644 index 0000000000..df9d593d9f --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/custom-graffiti.md @@ -0,0 +1,16 @@ +--- +description: "Add custom graffiti to your block proposals" +sidebar_label: "Custom Graffiti" +slug: /advanced-and-troubleshooting/advanced/custom-graffiti +unlisted: true +--- + +# Custom Graffiti + +By default, Charon adds a `charon/-` graffiti to all block proposals. This can be customized using the `--graffiti` and `--graffiti-disable-client-append` CLI flags. + +The `--graffiti` flag accepts either: +- A single string, which will be used by all validators, or +- A comma-separated list of strings, allowing each validator to have a unique graffiti (one string per validator). + +Each graffiti has a maximum length of 28 bytes to leave room for Charon to append a suffix containing the Obol signature, `OB`, and the specific consensus client type used, ``. This behavior can be disabled by setting the `--graffiti-disable-client-append` flag which also increases the maximum graffiti length to 32 bytes. \ No newline at end of file diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..f7e0c6e6de --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#getting-started-with-charon--the-builder-api) {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#client-configuration) {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#charon) {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#consensus-clients) {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](https://docs.obol.org/next/run/prepare/test-command#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#validator-clients) {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#verify-your-cluster-is-correctly-configured) {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [Ultrasound Relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. If you are using [Titan Relay](https://titanrelay.xyz), you can check their API by running `curl https://titanrelay.xyz/relay/v1/data/validator_registration?pubkey=0x123..456` with the public key of a validator in your cluster. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/fallback-beacon-node.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/fallback-beacon-node.md new file mode 100644 index 0000000000..c8a8306191 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/fallback-beacon-node.md @@ -0,0 +1,14 @@ +--- +description: "Add fallback beacon nodes to use when primary beacon node fails" +sidebar_label: "Fallback beacon nodes" +slug: /advanced-and-troubleshooting/advanced/fallback-beacon-node +unlisted: true +--- + +# Fallback beacon nodes + +Charon allows specifying multiple beacon node URL endpoints. It sends requests to all specified endpoints simultaneously and proceeds with the first response received. This approach improves reliability but increases the load on the beacon nodes. + +To mitigate this additional load, Charon supports configuring a fallback list of beacon nodes. These fallback nodes are only used if all primary beacon nodes fail to respond. This allows operators to designate less critical or public beacon nodes as a backup option, without impacting them under normal conditions. + +To configure fallback beacon nodes, provide a comma-separated list of beacon node URLs using the `--fallback-beacon-node-endpoints` CLI flag. \ No newline at end of file diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/nicknames.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/nicknames.md new file mode 100644 index 0000000000..13f1ab1720 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/nicknames.md @@ -0,0 +1,14 @@ +--- +description: "Add a nickname to your Charon node" +sidebar_label: "Nicknames" +slug: /advanced-and-troubleshooting/advanced/nicknames +unlisted: true +--- + +# Nicknames + +By default, Charon assigns each node a peer name by combining a random adjective with a random name from a predefined list. While these names are human-readable, they are not easily memorable or personalized for operators. + +You can set a personalized nickname for your Charon node by using the `--nickname` CLI flag followed by the desired string. This nickname is shared with other Charon nodes in the same cluster and included as a label in your Prometheus metrics. + +Nicknames can serve various purposes, such as providing a more memorable identifier, including a Discord ID for alerting, or adding a website URL for publicity. \ No newline at end of file diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..e27f0403c1 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.4.3 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. +::: diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..665ae37e44 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,105 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.4.3 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..8c80d667f8 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,38 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency and decentralization, you can opt to host your own relay on a separate open and static internet port. + +```shell +# Figure out your public IP +curl v4.ident.me + +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your public IPv4 or DNS hostname + +nano relay/docker-compose.yml + +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +Note that a local `relay/.charon/charon-enr-private-key` file will be created next to `relay/docker-compose.yml` to ensure a persisted relay ENR across restarts. + +A list of publicly available relays that can be used is maintained [here](../security/risks.md). diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/README.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/README.md new file mode 100644 index 0000000000..08d9fd5147 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Security" +slug: /advanced-and-troubleshooting/security +--- + +# security + diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/bug-bounty.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/bug-bounty.md new file mode 100644 index 0000000000..06a57d0d34 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/bug-bounty.md @@ -0,0 +1,181 @@ +--- +description: "Bug Bounty Policy" +sidebar_label: "Obol Bug Bounty Program" +slug: /advanced-and-troubleshooting/security/bug-bounty +--- + +# Obol Bug Bounty Program + +## Overview + +At Obol Labs, we prioritize the security of our distributed validator software and related services. Our Bug Bounty Program is designed to encourage and reward security researchers for identifying and reporting potential vulnerabilities. This initiative supports our commitment to the security and integrity of our products. + +## Participant Eligibility + +Participants must meet the following criteria to be eligible for the Bug Bounty Program: + +- Not reside in countries where participation in such programs is prohibited. +- Be at least 14 years of age and possess the legal capacity to participate. +- Have received consent from your employer, if applicable. +- Not have been employed or contracted by Obol Labs, nor be an immediate family member of an employee, within the last 12 months. + +## Scope of the Program + +Eligible submissions must involve software and services developed by Obol, specifically under the domains of: + +- Charon the DV Middleware Client +- Obol DV Launchpad and Public API +- Obol Splits Contracts +- Obol Labs hosted Public Relay Infrastructure + +Submissions related to the following are considered out of scope: + +- Social engineering +- Rate Limiting (Non-critical issues) +- Physical security breaches +- Non-security related UX/UI issues +- Third-party application vulnerabilities +- The [Obol](https://obol.org) static website or the Obol infrastructure +- The operational security of node operators running or using Obol software + +## Program Rules + +- Submitted bugs must not have been previously disclosed publicly. +- Only first reports of vulnerabilities will be considered for rewards; previously reported or known vulnerabilities are ineligible. +- The severity of the vulnerability, as assessed by our team, will determine the reward amount. See the "Rewards" section for details. +- Submissions must include a reproducible proof of concept. +- The Obol security team reserves the right to determine the eligibility and reward for each submission. +- Program terms may be updated at Obol's discretion. +- Valid bugs may be disclosed to partner protocols within the Obol ecosystem to enhance overall security. + +## Rewards Structure + +Rewards are issued based on the severity and impact of the disclosed vulnerability, determined at the discretion of Obol Labs. + +### Critical Vulnerabilities: Up to $100,000 + +A Critical-level vulnerability is one that has a severe impact on the security of the in-production system from an unauthenticated external attacker, and requires immediate attention to fix. Highly likely to have a material impact on validator private key security, and/or loss of funds. + +- High impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully exfiltrate BLS (not K1) private key material from a threshold number of operators in the cluster. +- Attacker that is not a member of the cluster can achieve the production of arbitrary BLS signatures from a threshold number of operators in the cluster. +- Attacker can craft a malicious cluster invite capable of subverting even careful review of all data to steal funds during a deposit. +- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield +- Direct loss of funds +- Permanent freezing of funds (fix requires hard fork) +- Network not being able to confirm new transactions (Total network shutdown) +- Protocol insolvency + +### High Vulnerabilities: Up to $10,000 + +For significant security risks that impact the system from a position of low-trust and require a significant effort to fix. + +- High impact, medium likelihood +- Medium impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully partition the cluster and keep the cluster offline indefinitely. +- Attacker that is not a member of the cluster can exfiltrate Charon ENR private keys. +- Attacker that is not a member of the cluster can destroy funds but cannot steal them. +- Unintended chain split (Network partition) +- Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments +- RPC API crash affecting projects with greater than or equal to 25% of the market capitalization on top of the respective layer +- Theft of unclaimed yield +- Theft of unclaimed royalties +- Permanent freezing of unclaimed yield +- Permanent freezing of unclaimed royalties +- Temporary freezing of funds +- Retrieve sensitive data/files from a running server: + - blockchain keys + - database passwords + - (this does not include non-sensitive environment variables, open source code, or usernames) +- Taking state-modifying authenticated actions (with or without blockchain state interaction) on behalf of other users without any interaction by that user, such as: + - Changing cluster information + - Withdrawals + - Making trades + +### Medium Vulnerabilities: Up to $2,500 + +For vulnerabilities with a moderate impact, affecting system availability or integrity. + +- High impact, low likelihood +- Medium impact, medium likelihood +- Low impact, high likelihood + +Impacts: + +- Attacker that is a member of a cluster can exfiltrate K1 key material from another member. +- Attacker that is a member of the cluster can denial of service attack enough peers in the cluster to prevent operation of the validator(s) +- Attacker that is a member of the cluster can bias the protocol in a manner to control the majority of block proposal opportunities. +- Attacker can get a DV Launchpad user to inadvertently interact with a smart contract that is not a part of normal operation of the launchpad. +- Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours +- Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network +- Charon cluster identity private key theft +- Rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle +- Charon public relay node is compromised and leads to cluster topologies getting discovered and disrupted +- Smart contract unable to operate due to lack of token funds +- Block stuffing +- Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol) +- Theft of gas +- Unbounded gas consumption +- Redirecting users to malicious websites (Open Redirect) + +### Low Vulnerabilities: Up to $500 + +For vulnerabilities with minimal impact, unlikely to significantly affect system operations. + +- Low impact, medium likelihood +- Medium impact, low likelihood + +Impacts: + +- Attacker can sometimes put a Charon node in a state that causes it to drop one out of every one hundred attestations made by a validator +- Attacker can display bad data on a non-interactive part of the launchpad. +- Contract fails to deliver promised returns, but doesn't lose value +- Shutdown of greater than 10% or equal to but less than 30% of network processing nodes without brute force actions, but does not shut down the network +- Changing details of other users (including modifying browser local storage) without already-connected wallet interaction and with significant user interaction such as: + - Iframing leading to modifying the backend/browser state (must demonstrate impact with PoC) +- Taking over broken or expired outgoing links such as: + - Social media handles, etc. +- Temporarily disabling user to access target site, such as: + - Locking up the victim from login + - Cookie bombing, etc. + +Rewards may be issued as cash, merchandise, or other forms of recognition, at Obol's discretion. Only one reward will be granted per unique vulnerability. + +## The following activities are prohibited by this bug bounty program + +- Any testing on mainnet or public testnet deployed code; all testing should be done on local-forks of either public testnet or mainnet +- Any testing with pricing oracles or third-party smart contracts +- Attempting phishing or other social engineering attacks against our employees and/or customers +- Any testing with third-party systems and applications (e.g. browser extensions) as well as websites (e.g. SSO providers, advertising networks) +- Any denial of service attacks that are executed against project assets +- Automated testing of services that generate significant amounts of traffic +- Public disclosure of an unpatched vulnerability in an embargoed bounty + +## Submission process + +To report a vulnerability, please contact us at security@obol.tech with: + +- A detailed description of the vulnerability and its potential impact. +- Steps to reproduce the issue. +- Any relevant proof of concept code, screenshots, or documentation. +- Your contact information. + +Incomplete reports may not be eligible for rewards. + +## Disclosure and Confidentiality + +Obol Labs will disclose vulnerabilities and the identity of the researcher (with consent) after remediation. Researchers are required to maintain confidentiality until official disclosure by Obol Labs. + +## Legal and Ethical Compliance + +Participants must adhere to all relevant laws and regulations. Obol Labs will not pursue legal action against researchers reporting vulnerabilities in good faith, but reserves the right to respond to violations of this policy. + +## Non-Disclosure Agreement (NDA) + +Participants may be required to sign an NDA for access to certain proprietary information during their research. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/contact.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/contact.md new file mode 100644 index 0000000000..0b4b54d4fd --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/contact.md @@ -0,0 +1,11 @@ +--- +description: "Security details for the Obol Network" +sidebar_label: "Contacts" +slug: /advanced-and-troubleshooting/security/contact +--- + +# Contacts + +Please email security@obol.tech to report a security incident, vulnerability, bug or inquire about Obol's security. + +Also, visit the [obol security repo](https://github.com/ObolNetwork/obol-security) for more details. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/ev-assessment.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/ev-assessment.md new file mode 100644 index 0000000000..3a666bf1e8 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/ev-assessment.md @@ -0,0 +1,293 @@ +--- +description: "Software Development Security Assessment" +sidebar_label: "Software Development at Obol" +slug: /advanced-and-troubleshooting/security/ev-assessment +--- + +# Software Development at Obol + +When hardening a projects technical security, team member's operational security, and the security of the software development practices in use by the team are some of the most criticial areas to secure. Many hacks and compromises in the space to date have been a result of these attack vectors rather than exploits of the software itself. + +With this in mind, in January 2023 the Obol team retained the expertise of Ethereal Venture's security researcher Alex Wade; to interview key stakeholders and produce a report into the teams Software Development Lifecycle. + +The below page is a result of the report that was produced. What is present here has had some sensitive information redacted, and contains responses to the recommendations made, detailing the actions the Obol team have taken to mitigate what has been highlighted. + +## Obol Report + +**Prepared by: Alex Wade (Ethereal Ventures)** **Date: Jan 2023** + +Over the past month, I worked with Obol to review their software development practices in preparation for their upcoming security audits. My goals were to review and analyze: + +* Software development processes +* Vulnerability disclosure and escalation procedures +* Key personnel risk + +The information in this report was collected through a series of interviews with Obol’s project leads. + +## Contents + +* Background Info +* Analysis - Cluster Setup and DKG + * Key Risks + * Potential Attack Scenarios +* Recommendations + * R1: Users should deploy cluster contracts through a known on-chain entry point + * R2: Users should deposit to the beacon chain through a pool contract + * R3: Raise the barrier to entry to push an update to the Launchpad +* Additional Notes + * Vulnerability Disclosure + * Key Personnel Risk + +## Background Info + +**Each team lead was asked to describe Obol in terms of its goals, objectives, and key features.** + +### What is Obol? + +Obol builds DVT (Distributed Validator Technology) for Ethereum. + +### What is Obol’s goal? + +Obol’s goal is to solve a classic distributed systems problem: uptime. + +Rather than requiring Ethereum validators to stake on their own, Obol allows groups of operators to stake together. Using Obol, a single validator can be run cooperatively by multiple people across multiple machines. + +In theory, this architecture provides validators with some redundancy against common issues: server and power outages, client failures, and more. + +### What are Obol’s objectives? + +Obol’s business objective is to provide base-layer infrastructure to support a distributed validator ecosystem. As Obol provides base layer technology, other companies and projects will build on top of Obol. + +Obol’s business model is to eventually capture a portion of the revenue generated by validators that use Obol infrastructure. + +### What is Obol’s product? + +Obol’s product consists of three main components, each run by its own team: a webapp, a client, and smart contracts. + +* [DV Launchpad](../../learn/intro/launchpad.md): A webapp to create and manage distributed validators. +* [Charon](../../learn/charon/intro.md): A middleware client that enables operators to run distributed validators. +* [Solidity](../../learn/intro/obol-splits.md): Withdrawal and fee recipient contracts for use with distributed validators. + +## Analysis - Cluster Setup and DKG + +The Launchpad guides users through the process of creating a cluster, which defines important parameters like the validator’s fee recipient and withdrawal addresses, as well as the identities of the operators in the cluster. In order to ensure their cluster configuration is correct, users need to rely on a few different factors. + +**First, users need to trust the Charon client** to perform the DKG correctly, and validate things like: + +* Config file is well-formed and is using the expected version +* Signatures and ENRs from other operators are valid +* Cluster config hash is correct +* DKG succeeds in producing valid signatures +* Deposit data is well-formed and is correctly generated from the cluster config and DKG. + +However, Charon’s validation is limited to the digital: signature checks, cluster file syntax, etc. It does NOT help would-be operators determine whether the other operators listed in their cluster definition are the real people with whom they intend to start a DVT cluster. So - + +**Second, users need to come to social consensus with fellow operators.** While the cluster is being set up, it’s important that each operator is an active participant. Each member of the group must validate and confirm that: + +* the cluster file correctly reflects their address and node identity, and reflects the information they received from fellow operators +* the cluster parameters are expected – namely, the number of validators and signing threshold + +**Finally, users need to perform independent validation.** Each user should perform their own validation of the cluster definition: + +* Is my information correct? (address and ENR) +* Does the information I received from the group match the cluster definition? +* Is the ETH2 deposit data correct, and does it match the information in the cluster definition? +* Are the withdrawal and fee recipient addresses correct? + +These final steps are potentially the most difficult, and may require significant technical knowledge. + +## Key Risks + +### 1. Validation of Contract Deployment and Deposit Data Relies Heavily on Launchpad + +From my interviews, it seems that the user deploys both the withdrawal and fee recipient contracts through the Launchpad. + +What I’m picturing is that during the first parts of the cluster setup process, the user is prompted to sign one or more transactions deploying the withdrawal and fee recipient contracts to mainnet. The Launchpad apparently uses an npm package to deploy these contracts: `0xsplits/splits-sdk`, which I assume provides either JSON artifacts or a factory address on chain. The Launchpad then places the deployed contracts into the cluster config file, and the process moves on. + +If an attacker has published a malicious update to the Launchpad (or compromised an underlying dependency), the contracts deployed by the Launchpad may be malicious. The questions I’d like to pose are: + +* How does the group creator know the Launchpad deployed the correct contracts? +* How does the rest of the group know the creator deployed the contracts through the Launchpad? + +My understanding is that this ultimately comes down to the independent verification that each of the group’s members performs during and after the cluster’s setup phase. + +At its worst, this verification might consist solely of the cluster creator confirming to the others that, yes, those addresses match the contracts I deployed through the Launchpad. + +A more sophisticated user might verify that not only do the addresses match, but the deployed source code looks roughly correct. However, this step is far out of the realm of many would-be validators. To be really certain that the source code is correct would require auditor-level knowledge. + +The risk is that: + +* the deployed contracts are NOT the correctly-configured 0xsplits waterfall/fee splitter contracts +* most users are ill-equipped to make this determination themselves +* we don’t want to trust the Launchpad as the single source of truth + +In the worst case, the cluster may end up depositing with malicious withdrawal or fee recipient credentials. If unnoticed, this may net an attacker the entire withdrawal amount, once the cluster exits. + +Note that the same (or similar) risks apply to validation of deposit data, which has the potential to be similarly difficult. I’m a little fuzzy on which part of the Obol stack actually generates the deposit data / deposit transaction, so I can’t speak to this as much. However, I think the mitigation for both of these is roughly the same - read on! + +**Mitigation:** + +It’s certainly a good idea to make it harder to deploy malicious updates to the Launchpad, but this may not be entirely possible. A higher-yield strategy may be to educate and empower users to perform independent validation of the DVT setup process - without relying on information fed to them by Charon and the Launchpad. + +I’ve outlined some ideas for this in #R1 and #R2. + +### 2. Social Consensus, aka “Who sends the 32 ETH?” + +Depositing to the beacon chain requires a total of 32 ETH. Obol’s product allows multiple operators to act as a single validator together, which means would-be operators need to agree on how to fund the 32 ETH needed to initiate the deposit. + +It is my understanding that currently, this process comes down to trust and loose social consensus. Essentially, the group needs to decide who chips in what amount together, and then trust someone to take the 32 ETH and complete the deposit process correctly (without running away with the money). + +Granted, the initial launch of Obol will be open only to a small group of people as the kinks in the system get worked out - but in preparation for an eventual public release, the deposit process needs to be much simpler and far less reliant on trust. + +Mitigation: See #R2. + +**Potential Attack Scenarios** + +During the interview process, I learned that each of Obol’s core components has its own GitHub repo, and that each repo has roughly the same structure in terms of organization and security policies. For each repository: + +* There are two overall github organization administrators, and a number of people have administrative control over individual repositories. +* In order to merge PRs, the submitter needs: + * CI/CD checks to pass + * Review from one person (anyone at Obol) + +Of course, admin access also means the ability to change these settings - so repo admins could theoretically merge PRs without needing checks to pass, and without review/approval, organization admins can control the full GitHub organization. + +The following scenarios describe the impact an attack may have. + +**1. Publishing a malicious version of the Launchpad, or compromising an underlying dependency** + +* Reward: High +* Difficulty: Medium-Low + +As described in Key Risks, publishing a malicious version of the Launchpad has the potential to net the largest payout for an attacker. By tampering with the cluster’s deposit data or withdrawal/fee recipient contracts, an attacker stands to gain 32 ETH or more per compromised cluster. + +During the interviews, I learned that merging PRs to main in the Launchpad repo triggers an action that publishes to the site. Given that merges can be performed by an authorized Obol developer, this makes the developers prime targets for social engineering attacks. + +Additionally, the use of the `0xsplits/splits-sdk` NPM package to aid in contract deployment may represent a supply chain attack vector. It may be that this applies to other Launchpad dependencies as well. + +In any case, with a fairly large surface area and high potential reward, this scenario represents a credible risk to users during the cluster setup and DKG process. + +See #R1, #R2, and #R3 for some ideas to address this scenario. + +**2. Publishing a malicious version of Charon to new operators** + +* Reward: Medium +* Difficulty: High + +During the cluster setup process, Charon is responsible both for validating the cluster configuration produced by the Launchpad, as well as performing a DKG ceremony between a group’s operators. + +If new operators use a malicious version of Charon to perform this process, it may be possible to tamper with both of these responsibilities, or even get access to part or all of the underlying validator private key created during DKG. + +However, the difficulty of this type of attack seems quite high. An attacker would first need to carry out the same type of social engineering attack described in scenario 1 to publish and tag a new version of Charon. Crucially, users would also need to install the malicious version - unlike the Launchpad, an update here is not pushed directly to users. + +As long as Obol is clear and consistent with communication around releases and versioning, it seems unlikely that a user would both install a brand-new, unannounced release, and finish the cluster setup process before being warned about the attack. + +**3. Publishing a malicious version of Charon to existing validators** + +* Reward: Low +* Difficulty: High + +Once a distributed validator is up and running, much of the danger has passed. As a middleware client, Charon sits between a validator’s consensus and validator clients. As such, it shouldn’t have direct access to a validator’s withdrawal keys nor signing keys. + +If existing validators update to a malicious version of Charon, it’s likely the worst thing an attacker could theoretically do is slash the validator, however, assuming Charon has no access to any private keys, this would be predicated on one or more validator clients connected to Charon also failing to prevent the signing of a slashable message. In practice, a compromised Charon client is more likely to pose liveness risks than safety risks. + +This is not likely to be particularly motivating to potential attackers - and paired with the high difficulty described above, this scenario seems unlikely to cause significant issues. + +## Recommendations + +### R1: Users should deploy cluster contracts through a known on-chain entry point + +During setup, users should only sign one transaction via the Launchpad - to a contract located at an Obol-held ENS (e.g. `launchpad.obol.eth`). This contract should deploy everything needed for the cluster to operate, like the withdrawal and fee recipient contracts. It should also initialize them with the provided reward split configuration (and any other config needed). + +Rather than using an NPM library to supply a factory address or JSON artifacts, this has the benefit of being both: + +* **Harder to compromise:** as long as the user knows launchpad.obol.eth, it’s pretty difficult to trick them into deploying the wrong contracts. +* **Easier to validate** for non-technical users: the Obol contract can be queried for deployment information via etherscan. For example:\ + ![](/img/gitbook/image-50.png) + +Note that in order for this to be successful, Obol needs to provide detailed steps for users to perform manual validation of their cluster setups. Users should be able to treat this as a “checklist:” + +* Did I send a transaction to `launchpad.obol.eth`? +* Can I use the ENS name to locate and query the deployment manager contract on etherscan? +* If I input my address, does etherscan report the configuration I was expecting? + * withdrawal address matches + * fee recipient address matches + * reward split configuration matches + +As long as these steps are plastered all over the place (i.e. not just on the Launchpad) and Obol puts in effort to educate users about the process, this approach should allow users to validate cluster configurations themselves - regardless of Launchpad or NPM package compromise. + +**Obol’s response** + +Roadmapped: add the ability for the OWR factory to claim and transfer its reverse resolution ownership. + +### R2: Users should deposit to the beacon chain through a pool contract + +Once cluster setup and DKG is complete, a group of operators should deposit to the beacon chain by way of a pool contract. The pool contract should: + +* Accept Eth from any of the group’s operators +* Stop accepting Eth when the contract’s balance hits (32 ETH \* number of validators) +* Make it easy to pull the trigger and deposit to the beacon chain once the critical balance has been reached +* Offer all of the group’s operators a “bail” option at any point before the deposit is triggered + +Ideally, this contract is deployed during the setup process described in #R1, as another step toward allowing users to perform independent validation of the process. + +Rather than relying on social consensus, this should: + +* Allow operators to fund the validator without needing to trust any single party +* Make it harder to mess up the deposit or send funds to some malicious actor, as the pool contract should know what the beacon deposit contract address is + +**Obol’s response** + +Roadmapped: give the operators a streamlined, secure way to deposit Ether (ETH) to the beacon chain collectively, satisfying specific conditions: + +* Pooling from multiple operators. +* Ceasing to accept ETH once a critical balance is reached, defined by 32 ETH multiplied by the number of validators. +* Facilitating an immediate deposit to the beacon chain once the target balance is reached. +* Provide a 'bail-out' option for operators to withdraw their contribution before initiating the group's deposit to the beacon chain. + +### R3: Raise the barrier to entry to push an update to the Launchpad + +Currently, any repo admin can publish an update to the Launchpad unchecked. + +Given the risks and scenarios outlined above, consider amending this process so that the sole compromise of either admin is not sufficient to publish to the Launchpad site. It may be worthwhile to require both admins to approve publishing to the site. + +Along with simply adding additional prerequisites to publish an update to the Launchpad, ensure that both admins have enabled some level of multi-factor authentication on their GitHub accounts. + +**Obol’s response** + +We removed individual’s ability to merge changes without review, enforced MFA, signed commits, and employed Bulldozer bot to make sure a PR gets merged automatically when all checks pass. + +## Additional Notes + +### Vulnerability Disclosure + +During the interviews, I got some conflicting information when asking about Obol’s vulnerability disclosure process. + +Some interviewees directed me towards Obol’s security repo, which details security contacts: [ObolNetwork/obol-security](https://github.com/ObolNetwork/obol-security), while some answered that disclosure should happen primarily through Immunefi. While these may both be part of the correct answer, it seems that Obol’s disclosure process may not be as well-defined as it could be. Here are some notes: + +* I wasn’t able to find information about Obol on Immunefi. I also didn’t find any reference to a security contact or disclosure policy in Obol’s docs. +* When looking into the obol security repo, I noticed broken links in a few of the sections in README.md and SECURITY.md: + * Security policy + * More Information +* Some of the text and links in the Bug Bounty Program don’t seem to apply to Obol (see text referring to Vaults and Strategies). +* The Receiving Disclosures section does not include a public key with which submitters can encrypt vulnerability information. + +It’s my understanding that these items are probably lower priority due to Obol’s initial closed launch - but these should be squared away soon! \[Obol response to latest vuln disclosure process goes here] + +**Obol’s response** + +we addressed all of the concerns in the obol-security repository: + +1. The security policy link has been fixed +2. The Bug Bounty program received an overhaul and clearly states rewards, eligibility, and scope +3. We list two GPG public keys for which we accept encrypted vulnerabilities reports. + +We are actively working towards integrating Immunefi in our security pipeline. + +### Key Personnel Risk + +A final section on the specifics of key personnel risk faced by Obol has been redacted from the original report. Particular areas of control highlighted were github org ownership and domain name control. + +**Obol’s response** + +These risks have been mitigated by adding an extra admin to the github org, and by setting up a second DNS stack in case the primary one fails, along with general Opsec improvements. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/overview.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/overview.md new file mode 100644 index 0000000000..d56083987f --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/overview.md @@ -0,0 +1,38 @@ +--- +description: "Security Overview" +sidebar_label: "Overview" +slug: /advanced-and-troubleshooting/security/overview +--- + +# Overview + +This page serves as an overview of the Obol Network from a security point of view. + +This page is updated quarterly. The last update was on 2024-June-19. + +## Table of Contents + +* [Overview](overview.md) + * [Table of Contents](overview.md#table-of-contents) + * [List of Security Audits and Assessments](overview.md#list-of-security-audits-and-assessments) + * [Security focused documents](overview.md#security-focused-documents) + * [Bug Bounty](overview.md#bug-bounty) + +## List of Security Audits and Assessments + +The completed audits reports are linked [here](https://github.com/ObolNetwork/obol-security/tree/main/audits). + +* A review of Obol Labs [development processes](./ev-assessment.md) by [Ethereal Ventures](https://www.etherealventures.com/). +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/) resulting in version [`v0.16.0`](https://github.com/ObolNetwork/charon/releases/tag/v0.16.0). +* A second [assessment of Charon](https://obol.tech/charon_quantstamp_assessment.pdf) by [QuantStamp](https://quantstamp.com/) resulting in version [`v0.19.1`](https://github.com/ObolNetwork/charon/releases/tag/v0.19.1). +* A [solidity audit](./smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* A [penetration testing certificate](https://github.com/ObolNetwork/obol-security/blob/main/audits/Sayfer_2024-03_Penetration_Testing_CFD.pdf) of the Obol DV Launchpad by [Sayfer](https://sayfer.io/). +* A second [solidity audit](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V2%20Audit%20-%20Nethermind.pdf) by [Nethermind](https://nethermind.io). + +## Security focused documents + +* A [threat model](./threat_model.md) for a DV middleware client like Charon. + +## Bug Bounty + +Information related to disclosing bugs and vulnerabilities to Obol can be found on [the next page](bug-bounty.md). diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/risks.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/risks.md new file mode 100644 index 0000000000..52a8d63881 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/risks.md @@ -0,0 +1,45 @@ +--- +description: "Centralization Risks and mitigation" +sidebar_label: "Centralization Risks and Mitigation" +slug: /advanced-and-troubleshooting/security/risks +--- + +# Centralization Risks and Mitigation + +## Risk: Obol hosting the relay infrastructure + +**Mitigation**: Self-host a relay. + +One of the risks associated with Obol hosting the [LibP2P relays](../../learn/charon/charon-networking.md) infrastructure allowing peer discovery is that if Obol-hosted relays go down, peers won't be able to discover each other and perform the DKG. To mitigate this risk, external organizations and node operators can consider self-hosting a relay. This way, if Obol's relays go down, the clusters can still operate through other relays in the network. Ensure that all nodes in the cluster use the same relays, or they will not be able to find each other if they are connected to different relays. + +The following non-Obol entities run relays that you can consider adding to your cluster (you can have more than one per cluster, see the `--p2p-relays` flag of [`charon run`](../../learn/charon/charon-cli-reference.md#the-run-command)): + +| Entity | Relay URL | +| ------------------------------------------- | ------------------------------------ | +| [DSRV](https://www.dsrvlabs.com/) | https://charon-relay.dsrvlabs.dev | +| [Infstones](https://infstones.com/) | https://obol-relay.infstones.com/ | +| [Hashquark](https://www.hashquark.io/) | https://relay-2.prod-relay.721.land/ | +| [Figment](https://figment.io/) | https://relay-1.obol.figment.io/ | +| [Node Guardians](https://nodeguardians.io/) | https://obol-relay.nodeguardians.io/ | + +## Risk: Obol being able to update Charon code + +**Mitigation**: Pin specific docker versions or compile from source on a trusted commit. + +Another risk associated with Obol is the Labs team having the ability to update the [Charon code](https://github.com/ObolNetwork/charon) used by node operators within DV clusters, which could introduce vulnerabilities or malicious code. To mitigate this risk, operators can consider pinning specific versions of the Docker image or git repo that have been [thoroughly tested](overview.md#list-of-security-audits-and-assessments) and accepted by the network. This would ensure that any updates are carefully vetted and reviewed by the community, and only introduced into a running cluster gradually. The labs team will strive to communicate the security or operational impact any Charon update entails, giving operators the chance to decide whether they want potential performance or quality of experience improvements, or whether they remain on a trusted version for longer. + +## Risk: Obol hosting the DV Launchpad + +**Mitigation**: Use [`create cluster`](../../learn/charon/charon-cli-reference.md#the-create-command) or [`create dkg`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) locally and distribute the files manually. + +Hosting the first Charon frontend, the [DV Launchpad](../../learn/intro/launchpad.md), on a centralized server could create a single point of failure, as users would have to rely on Obol's server to access the protocol. This could limit the decentralization of the protocol and could make it vulnerable to attacks or downtime. Obol hosting the launchpad on a decentralized network, such as IPFS is a first step but not enough. This is why the Charon code is open-source and contains a CLI interface to interact with the protocol locally. + +To mitigate the risk of launchpad failure, consider using the `create cluster` or `create dkg` commands locally and distributing the key shares files manually. + +## Risk: Obol going bust/rogue + +**Mitigation**: Use key recovery. + +The final centralization risk associated with Obol is the possibility of the company going bankrupt or acting maliciously, which would lead to a loss of control over the network and potentially cause damage to the ecosystem. To mitigate this risk, Obol has implemented a key recovery mechanism. This would allow the clusters to continue operating and to retrieve full private keys even if Obol is no longer able to provide support. + +A guide to recombine key shares into a single private key can be accessed [here](../advanced/quickstart-combine.md). diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/smart-contract-audit.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/smart-contract-audit.md new file mode 100644 index 0000000000..c23023dd88 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/smart-contract-audit.md @@ -0,0 +1,467 @@ +--- +sidebar_label: "Smart Contract Audit" +slug: /advanced-and-troubleshooting/security/smart-contract-audit +--- + +# Smart Contract Audit + +## Obol Audit Report: Obol Manager Contracts + +Prepared by: Zach Obront, Independent Security Researcher + +Date: Sept 18 to 22, 2023 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2023%20-%20Obol%20Splits%20V1%20Audit%20-%20Zach%20Obront.pdf) + +### About **Obol**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-obol) {#about-obol} +The Obol Network is an ecosystem for trust minimized staking that enables people to create, test, run & co-ordinate distributed validators. + +The Obol Manager contracts are responsible for distributing validator rewards and withdrawals among the validator and node operators involved in a distributed validator. + +### About **zachobront**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-zachobront) {#about-zachobront} +Zach Obront is an independent smart contract security researcher. He serves as a Lead Senior Watson at Sherlock, a Security Researcher at Spearbit, and has identified multiple critical severity bugs in the wild, including in a Top 5 Protocol on Immunefi. You can say hi on Twitter at [@zachobront](http://twitter.com/zachobront). + +### Summary & Scope[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary--scope) {#summary--scope} +The [ObolNetwork/obol-manager-contracts](https://github.com/ObolNetwork/obol-manager-contracts/) repository was audited at commit [50ce277919723c80b96f6353fa8d1f8facda6e0e](https://github.com/ObolNetwork/obol-manager-contracts/tree/50ce277919723c80b96f6353fa8d1f8facda6e0e). + +The following contracts were in scope: + +* src/controllers/ImmutableSplitController.sol +* src/controllers/ImmutableSplitControllerFactory.sol +* src/lido/LidoSplit.sol +* src/lido/LidoSplitFactory.sol +* src/owr/OptimisticWithdrawalReceiver.sol +* src/owr/OptimisticWithdrawalReceiverFactory.sol + +After completion of the fixes, the [2f4f059bfd145f5f05d794948c918d65d222c3a9](https://github.com/ObolNetwork/obol-manager-contracts/tree/2f4f059bfd145f5f05d794948c918d65d222c3a9) commit was reviewed. After this review, the updated Lido fee share system in [PR #96](https://github.com/ObolNetwork/obol-manager-contracts/pull/96/files) (at commit [fd244a05f964617707b0a40ebb11b523bbd683b8](https://github.com/ObolNetwork/obol-splits/pull/96/commits/fd244a05f964617707b0a40ebb11b523bbd683b8)) was reviewed. + +### Summary of Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary-of-findings) {#summary-of-findings} +| Identifier | Title | Severity | Fixed | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------- | ----- | +| [M-01](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) | Future fees may be skirted by setting a non-ETH reward token | Medium | ✓ | +| [M-02](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) | Splits with 256 or more node operators will not be able to switch on fees | Medium | ✓ | +| [M-03](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) | In a mass slashing event, node operators are incentivized to get slashed | Medium | | +| [L-01](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) | Obol fees will be applied retroactively to all non-distributed funds in the Splitter | Low | ✓ | +| [L-02](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) | If OWR is used with rebase tokens and there's a negative rebase, principal can be lost | Low | ✓ | +| [L-03](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) | LidoSplit can receive ETH, which will be locked in contract | Low | ✓ | +| [L-04](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) | Upgrade to latest version of Solady to fix LibClone bug | Low | ✓ | +| [G-01](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) | stETH and wstETH addresses can be saved on implementation to save gas | Gas | ✓ | +| [G-02](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) | OWR can be simplified and save gas by not tracking distributedFunds | Gas | ✓ | +| [I-01](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) | Strong trust assumptions between validators and node operators | Informational | | +| [I-02](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) | Provide node operator checklist to validate setup | Informational | | + +### Detailed Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#detailed-findings) {#detailed-findings} +#### \[M-01] Future fees may be skirted by setting a non-ETH reward token[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) {#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token} +Fees are planned to be implemented on the `rewardRecipient` splitter by updating to a new fee structure using the `ImmutableSplitController`. + +It is assumed that all rewards will flow through the splitter, because (a) all distributed rewards less than 16 ETH are sent to the `rewardRecipient`, and (b) even if a team waited for rewards to be greater than 16 ETH, rewards sent to the `principalRecipient` are capped at the `amountOfPrincipalStake`. + +This creates a fairly strong guarantee that reward funds will flow to the `rewardRecipient`. Even if a user were to set their `amountOfPrincipalStake` high enough that the `principalRecipient` could receive unlimited funds, the Obol team could call `distributeFunds()` when the balance got near 16 ETH to ensure fees were paid. + +However, if the user selects a non-ETH token, all ETH will be withdrawable only thorugh the `recoverFunds()` function. If they set up a split with their node operators as their `recoveryAddress`, all funds will be withdrawable via `recoverFunds()` without ever touching the `rewardRecipient` or paying a fee. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation) + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept) + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-1) + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-1) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendations) + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-2) + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-2) + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-3) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-3) + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-4) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-1) + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-4) + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-5) + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-2) + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-5) + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-6) + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-6) + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-7) + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-7) + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-8) + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-9) + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-10) + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\ diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..932cec0f71 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,155 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritize the liveliness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalize operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator. A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..1ed84c4d89 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# troubleshooting + diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..00244f1199 --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,295 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting anything other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using + +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +For now, ENR rotation/replacement is not supported, it will be supported in a future release. Therefore, its advised to always keep a backup of your `charon-enr-private-key` in a secure location (ex: cloud storage, USB Flash drive, etc.). + +### I can't find the keys anywhere + +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows.\ +Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + +## Lighthouse + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + +### Lighthouse gives the error `not enough time for a discovery seach` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues + +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance.\ +Using 3rd party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Can't connect to Beacon API` + +If you are running EL and CL outside Obol on the same machine, you might need to open ports in your firewall to allow connections incoming from the docker instance.\ +In order to know the IP of the docker network, run:`docker network inspect ` + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is\ +probably not online to sign successfully. Make sure all operators are\ +running the latest version of Charon. To check if some peers are not online:`docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key\ +should be created and placed in the right directory during the ceremony.\ +Also, make sure you are working in the right directory:`charon-distributed-validator-node`. + +### `Failed to confirm node connection` + +Wait for Teku & Lighthouse sync to be complete. + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum\ +limit has been reached. This is most often due to "maximum reservations per IP/peer".\ +This is when your Charon node is restarting or in some error loop and constantly\ +attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it.\ +This should allow the relay enough time to reset your IP/peer limits and\ +should then allow new reservations. This could also be due to the relay\ +being overloaded in general, so reaching a server wide "maximum connections"\ +limit. This is an issue with relay scalability and we are working in a long\ +term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO\_RESERVATION (204)\` indicates the peer\ +isn't connected to the relay, so the the Charon client cannot connect to the\ +peer via the relay. That might be because the peer is offline or the peer is\ +configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact\ +same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when\ +it failed to fetch the required data from the beacon node API. This indicates\ +a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation\ +duty failed in the fetcher component since it couldn't fetch the prerequisite\ +attestation data. This indicates the associated attestation duty failed to obtain\ +a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation\ +duty failed in the fetcher component since it couldn't fetch the prerequisite\ +aggregated v2 committee subscription. This indicates the associated prepare aggregation\ +duty failed due to no partial v2 committee subscription submitted by the cluster\ +validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation\ +duty failed in the fetcher component since it couldn't fetch the prerequisite\ +aggregated v2 committee subscription. This indicates the associated prepare aggregation\ +duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed\ +in the fetcher component since it couldn't fetch the prerequisite aggregated\ +RANDAO. This indicates the associated randao duty failed due to insufficient\ +partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed\ +in the fetcher component since it couldn't fetch the prerequisite aggregated\ +RANDAO. This indicates the associated randao duty failed due to no partial randao\ +signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed\ +in the fetcher component since it couldn't fetch the prerequisite aggregated\ +RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This\ +could indicate that insufficient honest peers participated in consensus or p2p\ +network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted\ +by the local validator client. This could indicate that the local validator client\ +is offline, or has connection problems with Charon, or has some other problem.\ +See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database\ +as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was\ +received from any peer. This indicates all peers are offline or p2p network connection\ +problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures\ +for the duty was received from peers. This indicates problems with peers or p2p\ +network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient\ +partial signatures failed. This indicates inconsistent signed data. This indicates\ +a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it\ +checks for a special file called the private key lock file. This file has the\ +same name as the ENR private key file but with a `.lock` extension.\ +If the private key lock file exists and is not older than 5 seconds, Charon won't\ +run. It doesn't allow running multiple Charon instances with the same ENR private\ +key. If the private key lock file has a timestamp older than 5 seconds, Charon\ +will replace it and continue with its work. If you\`re sure that no other Charon\ +instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the\ +validators private key shares don't match the ENR private key. There may\ +have been a mix-up during deployment, leading to a mismatching validator\ +client key share index. + +For example:Imagine node N is Alice, and node M is Bob, the error would read:`mismatching validator client key share index, Bob`s key share submitted to Alice`s charon node` Bob`s private key share(s) are imported to a VC that is connected to Alice`s Charon node. This is a invalid setup/deployment.\ +Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside\ +cluster-lock.json and see that matches with the public key inside`node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data first time around.\ +You can solve this by following the steps below: + +* Click the Wheel Icon > Datasources. +* Click prometheus. +* Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +* Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel + +Can be linked to a Teku keystore issue. + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + +``` +You can ignore this error unless you have been contacted by the Obol Team +with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. +``` + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly\ +on Linux and WSL for Windows systems. In the interest of security, the\ +charon docker image runs as a non-root user, and this user often does not\ +have the permissions to write in the directory you have checked out the code\ +to. This can be generally be fixed with some of the following: + +* Running docker commands with `sudo`, if you haven't [setup docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +* Changing the permissions of the `.charon` folder with the commands: + * `mkdir .charon` (if it doesn't already exist); + * `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + +``` +It`s because both Nethermind and Lighthouse start syncing and so there's +connectivity issues among the containers. Simply let the containers run for +a while. You won't observe frequent errors when Nethermind finishes syncing. You +can also add a second beacon node endpoint for something like Infura by +adding a comma separated API URL to the end of +`CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. +``` + +### How do I fix the `plugin "loki" not found` error? + +If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + +## Relay + +### `Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the\ +relay/docker-compose.yml with your real public IP or DNS hostname. + +### `Timeout resolving bootnode ENR: context deadline exceeded` + +The relay you are trying to connect to your peers via is offline or\ +unreachable. diff --git a/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..d10b59653d --- /dev/null +++ b/versioned_docs/version-v1.4/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or un-conctactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.4/api/address.mdx b/versioned_docs/version-v1.4/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.4/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.4/api/cluster-definition.mdx b/versioned_docs/version-v1.4/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.4/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.4/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.4/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..4da8ad1bcc --- /dev/null +++ b/versioned_docs/version-v1.4/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Effectiveness + + diff --git a/versioned_docs/version-v1.4/api/cluster-lock.mdx b/versioned_docs/version-v1.4/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.4/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.4/api/dv-exit.mdx b/versioned_docs/version-v1.4/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.4/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.4/api/metrics.mdx b/versioned_docs/version-v1.4/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.4/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.4/api/owr-information.mdx b/versioned_docs/version-v1.4/api/owr-information.mdx new file mode 100644 index 0000000000..0e20b4892a --- /dev/null +++ b/versioned_docs/version-v1.4/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR + + diff --git a/versioned_docs/version-v1.4/api/state.mdx b/versioned_docs/version-v1.4/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.4/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.4/api/system.mdx b/versioned_docs/version-v1.4/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.4/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.4/api/techne-credentials.mdx b/versioned_docs/version-v1.4/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.4/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.4/api/terms-and-conditions.mdx b/versioned_docs/version-v1.4/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..d5d32a5dba --- /dev/null +++ b/versioned_docs/version-v1.4/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TermsAndConditions + + + + diff --git a/versioned_docs/version-v1.4/api/what-is-this-api.md b/versioned_docs/version-v1.4/api/what-is-this-api.md new file mode 100644 index 0000000000..c1442d38ef --- /dev/null +++ b/versioned_docs/version-v1.4/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://holesky.launchpad.obol.org), a dapp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API will be made more easy for code-only interaction in the coming quarters with the release of the Obol-SDK. + +Read more about Obol and how to use the [launchpad](https://holesky.launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.4/community-and-governance/community/README.md b/versioned_docs/version-v1.4/community-and-governance/community/README.md new file mode 100644 index 0000000000..c8d5f1c1b9 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# community + diff --git a/versioned_docs/version-v1.4/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.4/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..6c09edfaa7 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/community/staking-masters.md @@ -0,0 +1,28 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\ + + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.4/community-and-governance/community/techne.md b/versioned_docs/version-v1.4/community-and-governance/community/techne.md new file mode 100644 index 0000000000..3152eb6b75 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/community/techne.md @@ -0,0 +1,119 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\ + + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. ::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.gg/obolnetwork) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.gg/obol) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.gg/obol) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.4/community-and-governance/contribution/README.md b/versioned_docs/version-v1.4/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..5cff17667a --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# contribution + diff --git a/versioned_docs/version-v1.4/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.4/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +````markdown + ```javascript + console.log(error); + ``` +```` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.4/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.4/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e17d6226af --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +- Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +- Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/README.md b/versioned_docs/version-v1.4/community-and-governance/governance/README.md new file mode 100644 index 0000000000..4dca7a7d08 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/README.md @@ -0,0 +1,57 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# Governance + +The Obol Collective is building a decentralized governance system rooted in the core values of Web3: transparency, openness, collaboration, and community-led decision making. At the same time, we recognize that decentralization is a journey, not a switch. Our aim is to progressively decentralize Obol governance in a way that is sustainable, resilient, and free of the common pitfalls that have emerged in the ecosystem. + +## Our Vision: Pragmatic Decentralization + +We are here to stay. And we believe the only way to build a resilient and successful decentralized collective is to start by building a strong foundation. In recent months, many leading DAOs have experienced operational bottlenecks, inefficiency, and growing pains from decentralizing too fast, too early. The result? Several are now walking back toward more centralized structures to regain coordination capacity, accountability, and operational agility. + +We’ve learned from these examples. Our approach is different: we are deliberately not rushing into maximal decentralization. Instead, we are laying the groundwork for progressive, sustainable decentralization over time. + +At this stage of the Collective, execution matters. Proposals are already going through governance processes, but the Obol Association still holds executional authority to move quickly where needed. We see this as a temporary and necessary condition to keep building and shipping. This balance, transparent governance with accountable execution, is critical to avoid decision paralysis. + +Governance at Obol is not about decentralization for its own sake. It is about enabling the best decisions for the long-term health of the network. As emphasized in the [Bell Curve governance roundtable](https://youtu.be/vF8XuRuZs9g?si=0dw3uh8gLXyvFlUH), decentralization without shared purpose or coordination leads to deadlock. We aim to build a governance model that supports rather than hinders progress. + +## Inspiration + +We draw inspiration from both the successes and challenges of other DAOs. In particular: + +* [**Arbitrum DAO**](https://forum.arbitrum.foundation/t/a-vision-for-the-future-of-arbitrum/28962), Introduced “Arbitrum Aligned Entities” to fix governance gridlock by assigning execution to focused teams, while keeping strategic control with the DAO. A response to over-decentralizing too quickly and losing operational clarity. +* [**Compound**](https://www.comp.xyz/t/proposal-to-create-the-compound-foundation/6777?utm_source=substack\&utm_medium=email), Proposed the Compound Foundation to help the DAO coordinate services, manage treasury execution, and maintain continuity — moving from pure DAO toward a hybrid model with accountable support. + +These initiatives reinforce our belief that progressive decentralization, aligned with clear domain ownership and accountable entities, leads to more sustainable governance. + +## Principles We Follow + +* **Decentralization is a means, not an end.** Governance exists to serve the network, not to complicate it. +* **Stakeholders should govern what they understand.** Validators and technical contributors guide protocol upgrades; token holders lead incentive and treasury decisions. +* **Social consensus is paramount.** On-chain votes matter, but upgrades only succeed through real-world coordination and adoption. +* **Structures must evolve with the protocol.** Governance at genesis won’t look like governance at maturity. We are building toward that future in deliberate steps. + +## Governance Tools + +To support transparent decision-making and empower active participation, here are key tools used across the Collective: + +* [**Governance Forum**](https://community.obol.org/) – for proposal discussion and coordination +* [**Voting Portal**](https://vote.obol.org/) – to delegate or vote on proposals +* [**Dune Dashboard**](https://dune.com/vistawtf/obol-governance) – to track voting data and delegate participation +* [**Staking Portal**](https://stake.obol.org/) – to stake OBOL and receive stOBOL +* [**0xretro.xyz**](https://0xretro.xyz/) – to access key info and metrics about delegates + +## Governance Sections + +The Obol governance documentation is organized into the following sections: + +* [collective.md](collective.md "mention") – framing the governance bodies, roles, and progressive decentralization pathway +* [token-house.md](token-house.md "mention") – the token-holder-based decision-making layer of the Collective +* [raf](raf/README.md "mention") – information for delegates participating in the Retroactive Funding Program (RAF) +* [grants-program](grants-program/README.md "mention") – the Obol funding mechanism for contributors and ecosystem support, led by the Obol Association + +_These sections evolve as the governance process matures. For any feedback, ideas, or questions, we invite you to join the discussion on the_ [_Forum_](https://community.obol.org/) _or reach out via_ [_Discord_](https://discord.gg/obol)_._ + +**Together, we are building governance for the long term.** diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/collective.md b/versioned_docs/version-v1.4/community-and-governance/governance/collective.md new file mode 100644 index 0000000000..4b93a757a8 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/collective.md @@ -0,0 +1,62 @@ +--- +description: "Obol Collective Overview" +sidebar_label: "Collective Overview" +slug: /community-and-governance/governance/collective +--- + +# Collective Overview + +## Purpose + +The Obol Collective’s governance system has two primary goals: + +1. **Resource allocation.** Allocate resources effectively to support the Collective’s vision and grow the Obol Collective's sustainable value. Long-term vision may sometimes conflict with short-term value creation; thus, governance requires a blend of short-term and long-term thinking to allocate the token treasury and protocol revenue effectively. +2. **Capture resistance.** Governance plays a key role in securing the anti-capture and censorship resistance of the Obol Collective. Governance should: + 1. make it possible for operations to continue over the long term without reliance on any individual entity; + 2. prevent any one entity or small group of entities from being able to control or censor. + +## Overview: The Obol Token House and RAF + +Two houses govern the Obol Collective: the Token House and the Obol RAF. + +In the **Token House,** OBOL Token holders are responsible for submitting, deliberating, and voting on governance proposals using the Governance Portal. Token holders can delegate their OBOL Token voting power to their own address or an eligible third party. Addresses with delegated voting power are called “Delegates”. + +In the **Obol Retroactive Fund (RAF)**, OBOL Token Delegates are responsible for allocating funds within the RAF to projects and teams that provide value to the Obol Collective. + +All OBOL holders and Delegates are expected to exercise their authority responsibly and follow the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. + +![](/img/gitbook/image-51.png) + +## The Security Council + +The Security Council is a committee of multi-sig wallet signers with the power to perform certain emergency actions as delegated to it by the Obol Association. + +The Security Council can execute any software upgrade or perform other emergency actions without delay to respond to a security emergency, should one arise. The Security Council must not use its power to perform Emergency Actions except in a true security emergency, such as a critical vulnerability that could significantly compromise the Obol Collective. + +After taking any Emergency Action, the Security Council must issue a full transparency report (at an appropriate time after the security emergency has passed) explaining what was done and why such action was justified. + +## Administration and Implementation + +In all cases, Obol Collective governance is intended to be carried out in a manner consistent with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. The Obol Association will steward this process as described below, with the goal of increasingly decentralising its role over time. + +The Obol Association, via its governance administrators, will facilitate administration to ensure that anyone may participate thoughtfully in governance. Such administrative services may include: + +* Moderation of governance proposals to ensure they are validly submitted and voted upon; +* Removal of proposals that reasonably appear to be fraudulent, spam-oriented, defamatory, hateful, or otherwise inappropriate or inconsistent with the values of the Collective; +* Monitoring of votes, voting power, the votable token supply, and voting periods for purposes of determining whether quorums and approval thresholds are met or accurately reflected; +* Management of mutually contradictory or duplicate proposals that are submitted simultaneously or close to one another; +* Maintenance of the Governance & RAF Portal; +* Other tasks that the Obol Association deems appropriate in connection with the above. + +The Association may also intervene operationally when necessary to uphold the integrity of the governance process — for instance, by removing improperly submitted proposals or enforcing community-agreed rules. When doing so, it will always act transparently and share justifications with the community. + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal or chosen RAF recipients, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails, coupled with an explanation. + +## Vision for Fully On-Chain Governance + +Once Collective’s governance develops and is deemed as sufficiently mature by the Obol Association, the implementations of passed proposals will follow full on-chain execution, where possible. Instead of the Collective’s reliance on the Obol Association for implementation, passed proposals will be moved to a queue to prepare for execution. The queue action will send the proposal to a Timelock contract, which starts a countdown until the proposal can be executed. + +Executing a proposal will run its function calls on-chain. Each proposal can be associated with one or more function calls. These calls will perform actions such as transferring assets from the treasury, updating the Governor's parameters, or calling another smart contract. diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/delegate-guide.md b/versioned_docs/version-v1.4/community-and-governance/governance/delegate-guide.md new file mode 100644 index 0000000000..8a249b10f6 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/delegate-guide.md @@ -0,0 +1,26 @@ +--- +description: "Delegate Guide" +sidebar_label: "Delegate Guide" +slug: /community-and-governance/governance/delegate-guide +--- + +# Delegate Guide + +## Delegate Rules of Engagement + +This document outlines the expectations, responsibilities, and values that should guide interactions within the Obol Collective governance community, including the Obol Forum, Discord, and working group meetings. This Code of Conduct will be reviewed periodically to incorporate feedback and adapt to governance needs. Any changes require community approval through the governance process. + +Please review these principles carefully to ensure alignment with the Obol Collective’s vision and commitment to a decentralized and sustainable ecosystem. + +Please read the rules of engagement on the forum [here](https://community.obol.org/t/delegates-rules-of-engagement/206). + +## **Governance Toolkit** + +These tools or their uses may change over time as governance evolves. For example, additional user interfaces dedicated to governance may be developed. Likewise, while voting currently takes place on-chain through the Governance Contract, some successful votes are administered and implemented by the Obol Association, which should not be the case indefinitely. + +Please see the toolkit on the forum [here](https://community.obol.org/t/governance-toolkit/207). + +## Delegates’ Role in the RAF +The role of Delegates in the RAF is to allocate votes to projects that have made substantial positive impact on the Obol Collective’s Decentralized Operator Ecosystem. Vote allocation is proportional to the Delegates’ delegated power. To determine the funding amounts, the [quadratic funding](https://qf.gitcoin.co/) mechanism is used, to ensure a balanced and equitable distribution of influence. + +Visit read [the delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) on the forum. \ No newline at end of file diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/README.md b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/README.md new file mode 100644 index 0000000000..c76526f661 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/README.md @@ -0,0 +1,88 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/governance/grants-program +--- + +# Grants Program + +⚠️ _The grants program is currently operating in its pilot phase._ + +_Following community feedback on this pilot, we’re committing to:_ + +* _Publishing an RFC-style post 2–3 weeks before each new wave_ +* _Involving delegates and external experts in future rounds via a grants committee_ +* _Extending this Pilot Wave application window to June 11 to give applicants more time_ +* _Maintaining limited scope and budget during the pilot to reduce risk and enable fast iteration_ + +_These changes aim to strengthen community trust, increase transparency, and enable broader governance participation over time._ + +*** + +## **Purpose** + +The Obol Grants Program (pilot) aims to support projects that advance the strategic goals of the Obol Collective by providing milestone-based funding to builders, educators, and contributors working on public goods aligned with the Distributed Validator (DV) ecosystem. + +This program is specifically designed to address the execution of the strategic SQUAD Goals outlined in [OIP-3](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/) that require community involvement. Each grant proposal must clearly align with **one of the grant tracks**, which reflect these goals. The grant tracks help ensure that funds are directed toward work that directly contributes to the Obol Collective's mission. + +To ensure proposals are aligned with these objectives, each track has a dedicated sub-page with: + +* A self-assessment checklist to help determine if the proposal is in scope +* Guidance on the types of contributions and initiatives encouraged +* Detailed evaluation criteria used to assess submissions + +## Structure + +* The program will operate in 8**-week waves**: + * **Application window:** 2 weeks + * **Review & approvals:** 2 weeks + * **Pause to keep track and provide guidance to the new projects**: 4 weeks +* **Milestone-based funding:** Grants are approved as a full proposal, but **funds are released per milestone**, once validated by the committee. Each proposal must define its expected milestones in advance. Applicants will have the opportunity to clearly outline their milestones during the application process. This includes describing the deliverables for each stage of the project and the success criteria for unlocking the next tranche of funding. A step-by-step guide to structuring and submitting milestone-based proposals is provided in a [dedicated sub-page](how-to-create-a-proposal-in-questbook.md). These milestones serve as checkpoints for disbursement and accountability. +* **Grant tracks aligned with** [**OIP-3 SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388)**:** + * [Boosting Obol DV Adoption](grant-track-for-boosting-obol-dv-adoption.md) + * [Establishing OBOL Token’s Role in DeFi & Governance](grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md) + * [Strengthening the Collective: Operators & Community Growth](grant-track-for-strengthening-the-collective-operators-and-community-growth.md) + +> **Funding Disclaimer:**\ +> The OBOL token amount will be calculated based on the USD value of your grant request using the market price of OBOL at the time your proposal is approved. That means the number of tokens may vary depending on the price at the time of approval. + +## Pilot Wave Timeline + +
PhaseDatesNotes
Applications OpenMay 14 – June 11Anyone can apply during this period
Review & ApprovalJune 12 - June 25Committee reviews proposals and approves based on milestone scope.
Publish recap of selected proposals and next steps
Pause & Monitoring June 26 - July 23Publish recap of selected proposals and next steps
+ +## Platform + +The program will be managed via [Questbook](https://questbook.app), with future integrations possible (Tally, etc). All proposals, reviewer activity, and milestone tracking will be transparent and publicly viewable. + +## Review Process + +* **Initial pilot approval committee**: 2 members from the Obol Association (Leo & Toma) +* **Later stages may expand to a formal committee & Tally-based voting** +* Reviews are rubric-based, and public by default within Questbook. These are structured scoring frameworks that help reviewers assess applications consistently across several criteria, such as: + + * Alignment with grant track and SQUAD goal(s) + * Feasibility and clarity of the milestones + * Potential impact and relevance to the Obol ecosystem + * Team capacity and track record + + Each grant track sub-page includes the specific rubric and criteria relevant to that category. + +## Budget + +* All **funding will be disbursed on a milestone basis only** _(see above disclaimer)_ +* Future quarterly or annual grant budgets to be approved by DAO governance +* The first pilot wave (Wave #1) will not specify any max budget. + +## Communication + +* Public recap of each wave will be posted on the Obol Forum + +## Future Upgrades + +* **Governance voting integration** via Tally +* **Expanded grant committee** with delegate participation +* **AI-assisted review workflows** if shown to increase efficiency + +## Transparency + +* The Obol Grants Program is currently hosted under Questbook's open-source plan +* All activity will remain publicly accessible through Questbook diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md new file mode 100644 index 0000000000..fb6dc80cdf --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md @@ -0,0 +1,88 @@ +--- +sidebar_label: "Grant Track for Boosting Obol DV Adoption" +slug: /community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption +--- + +# Grant Track for Boosting Obol DV Adoption + +The following guide will provide you with all the info you need to apply for a grant related to **Boosting Obol DV Adoption**. [You can apply directly on Questbook, here.](https://questbook.app/proposal_form/?grantId=6808de63300aee1f224f930a\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share) + +## Is My Proposal In-Scope for This Grant Track? + +This Grant Track seeks **technical integrations**, **infrastructure tooling**, and **adoption-driven initiatives** that accelerate the adoption of Obol DVs — especially in high-stake sectors like Liquid Staking, Restaking, and Community Squads. + +Proposals are **in-scope** if they: + +* Integrate Obol DVs into staking protocols (e.g. Lido v3, Etherfi, Swell, EigenLayer) +* Launch or grow community squads staking with DVs +* Build tools, dashboards, or deployment frameworks that reduce barriers to DV adoption +* Educate or onboard new users and node operators into the Obol ecosystem + +## Grant Track Priorities & Squad Goals + +This Grant Track hosts the following **Squad Goals** that represent Obol community priorities: + +#### **Category A – Deepen DVs penetration into (Re-)Staking Protocols** + +* Details: Integrate Obol DVs as the infrastructure layer of Liquid Staking & Restaking Protocols. Protocols represent about 37.5% of the Ethereum stake according to [Hildobby’s staking data](https://dune.com/hildobby/eth2-staking). Obol DVs currently [represent about 2%](https://obol.org/dashboard) of that stake. Example workstream: Collaborations with top protocols existing and new products (e.g., Lido v3, Etherfi eETH, Swell rswETH). +* Success Metrics: Make Obol DVs 10% of the Protocols Stake share. +* Exemples: + * Integrate Obol DVs into a Liquid Staking or Restaking protocol + * Build SDKs, APIs, or plugins that simplify DV integrations for protocols. + * Deployment scripts, wrapper contracts, REST APIs, infra automation tools + +#### **Category B – Deepen DVs penetration with community squads** + +* Details: Launch more community squads across the globe. Continue building launcher tooling and educational content on DVs to make squad staking easy. Currently Obol community squads run about 15,000 ETH. Example workstream: Programs to assist new node operators in setting up and fund Obol DVs. +* Success Metrics: + 1. 20 new community squads + 2. 25,000 ETH running on Obol DVs. +* Exemples: + * Create launcher tooling or deployment guides to enable squads. + * Run educational campaigns, community events, or node operator bootcamps + * Build dashboards, docs, or user-facing UX that reduces DV friction. + +## Milestone Articulation + +Grants in this track will be disbursed based on **clear, outcome-oriented milestones**, ideally aligned with measurable KPIs. + +Competitive grant requests include **3–5 milestones**, such as: + +* Signed protocol integration commitment +* Live testnet deployment +* Mainnet launch with DV cluster +* Target stake threshold hit (e.g., 1,000 ETH in DVs) +* Community feedback, docs, or case studies + +> 💡 Milestones should include both technical outcomes and adoption-based KPIs. + +## Security & Audit Requirements + +Proposals involving smart contract deployments must: + +* Document contracts clearly in the proposal +* If relevant, undergo audit from a reputable third-party auditor (e.g., Dedaub, ChainSecurity) +* Include audit as a funded milestone +* Complete audit before any mainnet funds are disbursed + +*** + +## What Makes a Strong Grant Request? + +* **Clear Impact**: Shows a measurable path to DV adoption across a protocol, institution, or community +* **Strong Team**: Has relevant experience in staking, infra, or validator tech +* **Ecosystem Fit**: Aligns with Obol's decentralization and resilience mission +* **Detailed Milestones**: Tied to real-world outcomes, not just deliverable completion +* **Sustainable Plan**: Long-term support considered (infra, community, updates) + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Applies To** | **Criteria** | +| ----------------------- | ----------------------- | ----------------------------------------------------------------- | +| DV Adoption Potential | All domains | How directly does this increase stake running on Obol DVs? | +| Technical Feasibility | Protocols, Institutions | Can this be realistically built by this team? | +| Stake Impact Projection | Protocols, Institutions | How much stake could realistically be secured with this proposal? | +| Ecosystem Alignment | All domains | Is this aligned with Obol's decentralization mission? | +| Milestone Clarity | All domains | Are deliverables concrete, verifiable, and meaningful? | +| Team Credibility | All domains | Does the team have relevant background or traction? | + diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md new file mode 100644 index 0000000000..4e02800624 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md @@ -0,0 +1,75 @@ +--- +sidebar_label: "Grant Track for Establishing OBOL Token’s Role in DeFi & Governance" +slug: /community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance +--- + +# Grant Track for Establishing OBOL Token’s Role in DeFi & Governance + +The following guide will provide you with all the info you need to apply for a grant related to Establishing OBOL Token’s Role in DeFi & Governance. [You can apply directly on Questbook, here](https://questbook.app/proposal_form/?grantId=6808df2e9ccae779614de4a6\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share). + +## Is My Grant Request In-Scope for This Grant Track? + +This Grant Track focuses on helping OBOL become a **core asset in Ethereum DeFi and protocol governance**, with emphasis on **TGE unlock success**, **on/off-chain liquidity**, and **DeFi integrations**. + +Your proposal is **in-scope** if it contributes to any of the following: + +* Improving liquidity of OBOL/stOBOL on DEXs and aggregators +* Deploying stOBOL as collateral or governance asset in DeFi protocols +* Developing tools, bridges, dashboards, or data integrations for OBOL +* Enhancing token UX or reputation (e.g. Chainlink oracles, analytics) + +> While the TGE and unlock strategy is centrally executed by the Obol Association, the community is encouraged to support OBOL's DeFi path via proposals, integrations, and partnerships. + +## Grant Track Priorities & Goals + +#### **Category A – Deep Liquidity & Market Presence** + +* Details: Provide ample liquidity so that participants can easily trade in and out of (st)OBOL. This ensures market confidence in the token being able to trade large volumes and sustain swings in price actions without too many negative effects such as slippage. +* Metrics: + * Deploy stOBOL as collateral on one Top 10 TVL DeFi Protocols (e.g. Morpho) +* Exemples: + * Design & deploy a stOBOL liquidity vault on Arrakis, Balancer, or Maverick + * Propose DAO-level liquidity incentives across DeFi venues + * Gauge votes, flywheels, or incentive co-funding with protocols. + * Deploy stOBOL as collateral in a major DeFi protocol + * Morpho, Aave, Compound, or FraxLend. Proposal should outline required steps (audits, onboarding, etc). + * Build integrations, bridges, or tools for token usability + * Token routers, zap tools, multi-chain bridges, UI UX support for using OBOL/stOBOL. + +## Milestone Articulation + +Grants will be disbursed based on **milestone-based funding**, with a focus on **liquidity outcomes**, **integration readiness**, and **community activation**. + +Typical milestones may include: + +* Smart contract deployment (vault, adapter, collateral wrapper) +* Governance proposal submission and/or approval +* Integration live on testnet/mainnet +* Trading volume or liquidity KPIs achieved (e.g. $1M TVL, $500K 30D volume) +* Community feedback incorporated or UI launched + +> Aim to tie final milestones to live integrations or measurable liquidity metrics. + +## Security Requirements + +* Smart contract deployments must be audited or forked from audited sources +* Where necessary, coordinate audits with the Obol Association +* Audit completion must be a milestone for DeFi protocol integrations + +## What Makes a Strong Proposal? + +* **Strategic Fit**: Aligns directly with OBOL’s token vision (see OIP-1 & OIP-2) +* **Credible Team**: Strong DeFi, token, or liquidity experience +* **Tangible Outcomes**: Focus on integrations, liquidity depth, or real utility +* **Governance Aware**: Engages with DAO or DeFi governance in a thoughtful way +* **Long-Term View**: Includes sustainability considerations (e.g. vault maintenance, fee-sharing) + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| --------------------------- | ---------------------------------------------------------------------------- | +| **Team Experience** | Demonstrates ability to execute in DeFi, integrations, or token infra | +| **Impact Potential** | Adds liquidity, unlocks new use cases, or supports long-term token utility | +| **Feasibility** | Proposal is technically and strategically realistic within a 3–6 month scope | +| **Alignment with Strategy** | Advances OBOL as a governance or collateral asset per OIPs & roadmap | +| **Clarity & Milestones** | Milestones are specific, measurable, and adoption-oriented | diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md new file mode 100644 index 0000000000..a9be8a9bb5 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md @@ -0,0 +1,73 @@ +--- +sidebar_label: "Grant Track for Strengthening the Collective: Operators & Community Growth" +slug: /community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth +--- + +# Grant Track for Strengthening the Collective: Operators & Community Growth + +The following guide will provide you with all the info you need to apply for a grant related to Strengthening the Collective: Operators & Community Growth. [You can apply directly on Questbook, here](https://questbook.app/proposal_form/?grantId=6808e08e9ccae779614e2cfe\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share). + +## Is My Proposal In-Scope for This Grant Track? + +This Grant Track funds work that builds **capabilities and coordination** within the Obol ecosystem — especially among distributed validator operators and active Collective members. + +You’re likely in-scope if your proposal: + +* Trains, certifies, or supports DV operators in joining Obol clusters +* Improves the Silver Techne onboarding experience, curriculum, or support +* Builds infrastructure, guides, or dashboards to track operator activity or status + +Whether you’re focused on operator growth, or ecosystem education — we want to hear from you. + +## Grant Track Priorities & **Goal**s + +#### **Category A – Operator Development (Silver Techne)** + +* Details: Train and certify a professional class of operators who can scale networks reliably by running Obol DVs. Currently there is [about 600 Silver Techne credentials](https://etherscan.io/token/0xfdb3986f0c97c3c92af3c318d7d2742d8f7ed8cc). +* Success Metrics: Grow the number of Silver Techne Credentials by 30%. +* Exemples: + * Design or improve training content for Silver Techne + * Docs, videos, interactive workshops, validator testnets + * Build or enhance certification workflows and dashboards + * UX to issue/review credentials, operator leaderboards, cluster-readiness tools + * Regionalize operator onboarding programs + * Language localization, timezone-based support, squad coordination templates + +> These proposals should prioritize transparency, inclusion, and fair access for contributors. + +## Milestone Articulation + +Grants are paid out in **staged milestones** that reflect real-world progress and value delivered to the operator ecosystem or community. + +Examples of strong milestones: + +* Training curriculum published, piloted with 20 new operators +* 50+ new Silver Techne credentials issued (with wallet verification) +* Launch of open project board with real-time community activity + +## Security & Credibility Notes + +Grant Requests that touch credentialing, access controls, or public dashboards must: + +* Respect contributor privacy and security +* Be reviewed by at least one Collective contributor for community fit +* Prioritize open-source and reproducible tooling wherever possible + +## What Makes a Strong Grant Request? + +* **Community Fit**: Proposal aligns with Obol’s mission of decentralization and collective stewardship +* **Operator Support**: Drives real growth in the Silver Techne operator pool or quality of operator experiences +* **Transparency**: Proposes open processes, accessible documentation, and easy participation +* **Sustainability**: Suggests systems that can scale or run with community ownership +* **Clear Value**: Tied to quantifiable growth in contributions, certifications, or community activity + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| ------------------------- | -------------------------------------------------------------------------------- | +| **Team Experience** | Is the team familiar with validator ops, contributor tools, or community design? | +| **Impact Potential** | Will this grow or support long-term contributor or operator engagement? | +| **Technical Feasibility** | Is the proposal scoped realistically and implementable with the given resources? | +| **Milestone Clarity** | Are there measurable indicators of success and clear timelines for each phase? | + +\ diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md new file mode 100644 index 0000000000..1a4560536f --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md @@ -0,0 +1,90 @@ +--- +sidebar_label: "How to create a proposal in Questbook?" +slug: /community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook +--- + +# How to create a proposal in Questbook? + +This guide walks you through the full process of preparing and submitting a grant proposal to the Obol Grants Program using [Questbook](https://questbook.app). + +### 1. Respect the Wave Schedule + +Each grant wave follows a strict timeline. Grant requests must be submitted during the **application window** listed in the [Grants Program page](./). + +> ⚠️ Proposals submitted outside of an open wave window will **not** be considered. + +*** + +### 2. Choose the Right Grant Track + +Your grant request must clearly align with **one of the three main grant tracks**, which are tied to the Obol Collective's SQUAD goals. Each track has its own page with: + +* Scope verification checklist +* Expectations and contribution types +* Evaluation criteria used during review + +_**On each grant track page, you will find the link to apply for that specific track on Questbook.**_ + +👉 Visit the grant track guides linked [here](./#structure). + +*** + +### 3. Prepare to Submit on Questbook + +#### If you don't already have a Questbook account: + +* Go to [https://questbook.app](https://questbook.app) +* Create a new wallet or connect an existing one +* Back up your wallet's private key securely — you will need it to access your account + +*** + +### 4. Create Your Application + +1. Select the grant **track** aligned with your grant request and follow the link provided in the dedicated subpage +2. Complete each section of the form, including: + * Project summary + * Team & track record + * Grant track alignment + * Milestones & timelines + * Requested funding & deliverables per milestone + +Each section is pre-structured to guide you in providing the expected information. + +*** + +### 5. Include Your Cost Breakdown + +You must attach a cost breakdown using the **template provided by the Obol Association** (linked below). + +* You may modify the structure, add/remove rows, or use your own format if clearly structured. +* Make sure costs are tied to **milestones**, not just a lump sum. + +👉 [Download the cost breakdown template here](https://docs.google.com/spreadsheets/d/10QoterGwLTZyeCf8yShOuGOaLybJd23qrzHnd28J7AM/edit?usp=sharing) + +*** + +### 6. Post in the Forum + +Once your application is submitted on Questbook: + +* Go to the [**Obol Grants Forum Thread**](https://community.obol.org/t/obol-grants-wave-1-submissions-thread/525) +* Post a comment with: + * Your project name + * A short summary + * A link to your Questbook grant request + +This ensures community visibility and transparency. + +*** + +### 7. What Happens Next + +* During the review period (after the wave closes), your grant request will be evaluated by the current committee. +* Reviews will use the rubric published in your track’s page to evaluate your request. +* Feedback may be shared on Questbook or through the forum. + +**If approved:** + +* You’ll be contacted for milestone validation and next steps for funding. +* Disbursements will occur **after milestone delivery is validated.** diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/raf/README.md b/versioned_docs/version-v1.4/community-and-governance/governance/raf/README.md new file mode 100644 index 0000000000..730a7c92da --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/raf/README.md @@ -0,0 +1,76 @@ +--- +description: "The RAF" +sidebar_label: "The RAF" +slug: /community-and-governance/governance/raf +--- + +# The RAF + +Obol’s Retroactive Funding (RAF) mechanism is designed to strengthen and promote the decentralisation of Ethereum's settlement layer by rewarding projects that add value and drive impact for Ethereum’s decentralisation. Read more about the Obol RAF [here](https://blog.obol.org/1-percent-for-decentralisation/). + +Voting and funding distributions occur over a series of **Obol Retroactive Fund (RAF)** rounds, with OBOL token Delegates determining how funds from the RAF are allocated. The first RAF round will open in February 2025. + +## Overview of the Obol RAF: + +* Any project that meets the RAF round’s criteria can make an application. +* OBOL Token Delegates vote on applications proportional to their delegated power and using [quadratic funding](https://qf.gitcoin.co/). +* The Obol RAF rounds occur at intervals and include phases for scoping, application creation, application review, voting, and funding distribution. +* The Obol Association will collect information from projects to distribute grants, including KYC, where required. + +Below is described the steps within each RAF round. Each step takes approximately one week.\\ + +![](/img/gitbook/image-53.png) + +### Step 1: Scoping + +The scope of the round’s impact and the amount of funding to be allocated is defined by the Obol Association at the outset of the round and posted on the Obol Forum. + +### Step 2: Application Registration + +Projects are invited to create an application on the [RAF App](http://raf.obol.org/). Any project or team can apply, but in the future, governance may decide that an application needs to be made by someone holding a minimum amount of OBOL tokens. + +Once a RAF round is opened, to apply for the Obol RAF, projects can create an application on [raf.obol.org](http://raf.obol.org/) by following these steps: + +1. **Create an Application:** Fill out the application form using the [RAF App](http://raf.obol.org/). +2. **Describe Impact:** Specify the category of the project and its impact. + +### Step 3: Application Review + +A subset of OBOL Delegates appointed by the Obol Association reviews applications to ensure compliance with the application rules. + +The Obol Association will also review applications to filter out spam or applications that do not align with the mission of the Obol Collective. + +### Step 4: Voting + +OBOL Delegates vote on projects in proportion to their voting power. Here’s how it works: + +1. **Eligibility:** Every address that has been delegated voting power by OBOL Token holders can submit votes. +2. **Voting Process:** Delegates vote using the [raf.obol.org](http://raf.obol.org) app. Depending on the type of application being reviewed, a specific set of criteria should be used to judge a project's contributions to the Obol Collective. + +:::warning +The Obol Association will monitor votes to ensure contributors are not voting for projects they are directly involved in or where a substantial conflict of interest may be present. Delegates are expected to act in accordance with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. +::: + +### Step 5: Tallying Results + +The voting power of each OBOL Token Delegate is proportional to the amount of OBOL tokens delegated to them. However, the funding results are calculated using [quadratic funding](https://qf.gitcoin.co/), meaning that the square root of the votes is used to determine the final allocation. This approach ensures a broader distribution of funding across the Obol Collective, rather than allowing a small number of winners to dominate. + +### Step 6: Compliance + +The Obol Association will review the list of selected projects, adjust if necessary and collect information from them to distribute the grant legally compliantly (including completing KYC if required). + +### Step 7: Funding distribution + +The overall reward amount for the round is divided among the winning projects based on the delegates' vote and allocation according to the quadratic funding mechanism. + +### **Step 8: Community retrospective** + +After each round, The Obol Association will conduct a retrospective and gather community feedback. + +## Guides for each Round + +RAF1: see the [RAF1 guide](https://community.obol.org/t/guide-for-raf-round-1-raf1/227) in the forum. + +## RAF1 Summary & Insights + +Head over to [raf-1.md](raf-1.md "mention") to find the results, top projects, and key takeaways from our first round. diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/raf/raf-1.md b/versioned_docs/version-v1.4/community-and-governance/governance/raf/raf-1.md new file mode 100644 index 0000000000..873644c724 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/raf/raf-1.md @@ -0,0 +1,27 @@ +--- +sidebar_label: "RAF #1" +slug: /community-and-governance/governance/raf/raf-1 +--- + +# RAF #1 + +## Learnings from RAF Round 1 + +Our first Retroactive Funding round (RAF1) awarded 1 million OBOL to 46 projects using a quadratic voting mechanism. Projects were evaluated on technical impact, contribution to decentralization, and public goods alignment. + +### Top-funded projects included: + +* Dappnode — integrated Obol into their Dappstore, enabling 16k+ validators to use Obol setups. +* Ethereum on ARM — ran distributed validators on low-cost devices. +* Stereum — offered one-click node deployment with Obol pre-installed, backed by strong GitHub and beaconcha.in adoption metrics. + +### Key learnings: + +* Impact evaluation is challenging without clear data; future rounds may require stronger entry thresholds. +* Quadratic voting worked to elevate broadly supported projects, but needed clearer onboarding. +* Delegates requested better UX for wallets and real-time visibility into vote progress. +* Community engagement was strong but limited in feedback volume — improving outreach will be a focus + +_**We’re using these insights to shape future RAF rounds, with an emphasis on transparency, fairness, and long-term ecosystem impact.**_ + +👉 [Read the full blog post here](https://blog.obol.org/raf1-results/) diff --git a/versioned_docs/version-v1.4/community-and-governance/governance/token-house.md b/versioned_docs/version-v1.4/community-and-governance/governance/token-house.md new file mode 100644 index 0000000000..e37937aa0b --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/governance/token-house.md @@ -0,0 +1,119 @@ +--- +description: "The Token House" +sidebar_label: "The Token House" +slug: /community-and-governance/governance/token-house +--- + +# The Token House + +In the Token House, OBOL Token holders are responsible for submitting, deliberating, and voting on various Obol Collective governance proposals. + +## Overview of the Obol Token House + +* Proposals are reviewed and voted on in three-week cycles. + +:::info +You can subscribe to the public calendar [here](https://calendar.google.com/calendar/u/0?cid=Y183YzQ0ZmYwZjM5ODE4ZTcyODg2OTM2MmI4ZWEyMGNmMDdhMmZmMmZiMzMxYjE2MjMwYzg3ZjQxZGRiYjA4N2ViQGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20\&ref=blog.obol.org) so you always know where the current cycle stands. +::: + +* In the first week, anyone may draft a proposal of any type based on [this template](https://community.obol.org/t/proposal-template/208) and post it on the [Forum](https://community.obol.org/) with \[Draft] in the title. Delegates, Obol Collective members, and the general public can provide feedback on proposals in the forum, which should be incorporated into the proposal using the author’s best judgment. +* Once your proposal has been approved by four top-100 Delegates (by voting power), add a link to your proposal to the Voting Cycle Roundup forum thread by the last day of Week 2, and update the title from \[Draft] to \[Final]. The proposal then moves on to Week 3: Voting. +* If your proposal is passed, the Obol Association will facilitate its administration, including distributing approved OBOL Tokens grants. +* If your proposal fails, you can make a new proposal in the next cycle, specifying how you have incorporated significant changes from your first proposal.\\ + + ![](/img/gitbook/Token_house.png) + +## Token House Governance Proposal Process + +Anyone can submit a proposal to the Token House by using the Governance Portal. Proposals are accepted or rejected using a voting process. A proposal must be one of the valid proposal types listed below and follow the voting process described here. + +All governance proposals go through a 3-week cycle. Each “week” runs from Thursday at 7:00 pm GMT until Wednesday at 7:00 pm GMT. + +### Valid Proposal Types + +All governance proposals must fall within one of the following categories: + +* Ecosystem grants +* Protocol upgrades +* Token inflation adjustment +* Treasury allocations +* Work agreements +* Veto on the Obol RAF operations + +The different requirements for submission and approval of each Proposal Type are summarized below. If a specific template is not specified below, proposals should follow this standard proposal template. + +All Ecosystem grant applications are processed by the Association. + +Below are listed types of Token House Proposals. Each has a two-week review period plus one week voting window, with an approval threshold of 51%. + +| Proposal Type | Description | Submission Requirements | +| :-----------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------- | +| Ecosystem grants | The Obol Association’s treasury may be used to support development of the Collective and/or growth of the ecosystem via the proposal template. | Forum proposal + On-Chain Voting | +| Token inflation adjustment | Changes to the OBOL Token Contract or its supply. | Forum proposal + On-Chain Voting | +| Treasury Appropriations | The amount of OBOL Tokens the Obol Association may spend or distribute annually | Proposal initiated by the Association + On-Chain Voting | +| Work agreements | Formal arrangements between the Obol Association and contributors, teams, or organizations tasked with advancing specific initiatives or responsibilities within the ecosystem | Forum proposal + On-Chain Voting | +| Veto on the Obol RAF operations | The veto mechanism serves as a safeguard against decisions or actions within the RAF operations that are misaligned with the mission of decentralization, transparency, or the collective interests of the community. | Forum proposal + On-Chain Voting | +| Protocol upgrades | Scheduled changes to the on-chain smart contracts comprising the protocol or governance contracts. | Forum proposal + On-Chain Voting | +| SQUAD Goals | It reflects the aim of establishing shared, strategic, and community-driven objectives. Goals are set annually, with each cycle beginning in April. | Forum proposal + On-Chain Voting | + +### Weeks 1-2: Feedback and Review + +All proposal types should be posted to the [Obol Forum](https://community.obol.org/) for review. Proposal authors are expected to respond to feedback from Obol Collective members and Delegates. + +Proposals should be: + +* Submitted as a new discussion thread on the [Governance Forum](http://community.obol.tech/) in the appropriate Proposal Category. +* Marked with \[Draft] in the title. +* Formatted and contain information consistent with the [standard proposal template](https://community.obol.org/t/proposal-template/208). + +Before the end of Week 2, a governance administrator will create a Voting Cycle Roundup thread in the forum summarising all the proposals that meet the voting requirements for Week 3 Voting. + +For proposals to proceed to Week 3, four of the top 100 delegates by voting power must give explicit approval on the discussion thread. Delegates may signal approval by pasting the following comment on the proposal discussion thread: _”I am an Obol Delegate \[link to your delegate commitment in your Tally profile] with sufficient voting power, and I believe this proposal is ready to move to a vote."_ + +If a Delegate approves a proposal to move to a vote, it does not endorse that proposal. It simply signifies that they believe the proposal is ready to move to a vote. + +After receiving the required approvals, the author should update the proposal title from \[Draft] to \[Final] and add a link to their proposal in the Voting Cycle Roundup thread by the last day of Week 2 at 19:00 GMT. Authors should also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal’s progress. Proposal authors should include relevant links if feedback was gathered outside the Forum (e.g., on Discord). + +If a proposal author does not get explicit approval or wants more time for feedback, they should not include their proposal in the Voting Cycle Roundup thread. Instead, they should continue to seek community feedback and submit an updated proposal in the next voting cycle. + +:::warning +If a proposal that did not receive explicit approval through the steps above is submitted to the voting portal, the Obol Association reserves the right to cancel it onchain. While the Association is currently working to formalize this cancel authority within the Governor contract, this measure helps preserve governance integrity and ensures that only properly vetted proposals are voted on. +::: + +### Week 3: Publish a Proposal Onchain and Voting + +During Week 3, a wallet holding at least [30,000 OBOL in voting power](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c#readContract) must publish the proposal on the [Obol Governance Platform](https://www.tally.xyz/gov/obol). + +\ +After publication, there is a 24-hour voting delay, during which the proposal can be canceled if necessary. The voting delay is the amount of time between when a proposal is submitted and when it goes up for voting. The delay gives token holders time to delegate their voting power before the vote starts or buy more votes. Governor takes a snapshot of all the voting power at the start of voting. Read more [here](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/how-to-pick-governor-parameters#how-to-pick-the-voting-delay). + +\ +After the 24 hours, Delegates (including OBOL Token holders who have self-delegated) vote on proposals via the [Obol Governance Portal](https://vote.obol.org/). All proposals are included in voting if they were added to the Voting Cycle Roundup thread before the deadline and have the approval of four top-100 delegates. + +A governance proposal is **approved** if it satisfies two requirements: + +* **Quorum:** A minimum number of OBOL Token votes measured as _a % of the total votable OBOL Token supply, as of the start of the voting period._ “Votable supply” is the total amount of OBOL Tokens that have been delegated (including to oneself) and, therefore, can participate in voting. The current definition for the OBOL Token House is 0.84% of minted supply. +* **Approval threshold:** The minimum _% of votes cast in support relative to the total number of votes._ The current definition for the OBOL Token House is 0.01% of minted supply. + +A snapshot is taken at the start of each voting period to determine each delegate’s voting power. Voting is hosted on the Obol Governance Portal. + +If a proposal is submitted for a vote and does not pass, the proposal will not be executed. If a proposal author wishes to iterate on a rejected proposal, they should: + +1. Create a new proposal thread on the Forum. +2. Include a link to the first proposal that did not pass. +3. Clearly identify what has changed in the new proposal. + +:::warning +If the same proposal fails to pass two consecutive times (i.e., it is rejected onchain twice in a row), it may not be reintroduced or submitted again for a minimum period of **10 governance cycles** — roughly equivalent to **7 months** (based on the current 3-week cycle length). This ensures that only well-formed, broadly supported proposals proceed and discourages repeated cycling of the same topic without meaningful revision or support. +::: + +### Timelock Delay + +After the voting period ends, if the proposal passes, there will be a 5-day timelock delay. The timelock delay is the minimum time required between the approval and execution of a proposal. This delay gives stakeholders a final opportunity to review and react before the proposal is implemented. Read more [here](token-house.md#implementation). + +## Implementation + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails. diff --git a/versioned_docs/version-v1.4/community-and-governance/obol-token/README.md b/versioned_docs/version-v1.4/community-and-governance/obol-token/README.md new file mode 100644 index 0000000000..71712b7cc7 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/obol-token/README.md @@ -0,0 +1,114 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/obol-token +--- + +# The OBOL Token + +The OBOL Token is central to the governance and operation of the Obol Collective. It serves multiple purposes that are essential to its functioning. + +**OBOL Token Transferability:** With the approval of[ OIP-2](https://community.obol.org/t/oip-2-unlock-obol-token/317/30), the OBOL Token is set for a strategic and well-planned unlock. The tokens will be unlocked on the 7th May 2025 at 11:00 UTC, following the completion of centralized exchange listings. Please go to [claim.obol.org](https://claim.obol.org) to unlock airdrop tokens. + +## Token Contract + +The official token contract address of the OBOL Token is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7) + +## Official Uniswap Pool + +The Uniswap Pool funded by the Obol Association is [https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434](https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434) + +## Verified Contract Addresses + +The following smart contracts power OBOL staking, governance, and reward distribution on Ethereum mainnet. + +
+ +Governor Contract + +* **Address:** [`0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c`](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c) + +- **Purpose:** Manages onchain proposal lifecycle and voting logic for Token House governance. + +* **What you can find onchain:** + * Voting thresholds + * Quorum settings, + * Delay/period configs, + * Proposal and vote history. + +
+ +
+ +Obol Staker + +* **Address:** [`0x30641013934ec7625c9e73a4D63aab4201004259`](https://etherscan.io/address/0x30641013934ec7625c9e73a4D63aab4201004259) + +- **Purpose:** This is the base layer of the Obol staking system. It facilitates the basic mechanics of staking, such as managing deposits, forwarding governance delegation, and streaming rewards based on earning power. + +* **What you can find onchain:** + * Total OBOL staked in the contract + * Stake, earning power, rewards and balances on a granular, per-deposit basis + * Current reward rate and configuration + * Contract events (e.g. `Staked`, `Withdrawn`) + * Interactions for staking/unstaking + +
+ +
+ +stOBOL (ERC-20 Token Contract) + +* **Address:** [`0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC`](https://etherscan.io/address/0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC) + +- **Purpose:** A liquid ERC-20 representation of staked OBOL built on top of the Obol Staker. It adds features like transferability, reward auto compounding, and the ability to use a staked OBOL position in other protocols. Holders retain the ability to delegate their staked tokens to the governance delagate of their choice. + +* **What you can find onchain:** + * ERC-20 metadata (name, symbol, decimals) + * Total supply and balances + * Transfer history + * Allowances / approvals + * Voting power interface (via `getVotes` and `delegates`) + * Event logs for delegation changes + +
+ +
+ +Reward Notifier + +* **Address:** [`0x384dd81047F88eE35DE75DA1149943B8e62d8802`](https://etherscan.io/address/0x384dd81047F88eE35DE75DA1149943B8e62d8802) + +- **Purpose:** Manages the distribution of tokens to the staking contract so they can be streamed as rewards to stakers. + +* **What you can find onchain:** + * Current and past reward rate values + * Administrative role settings (who can push updates) + * Timing/config changes made through proposals + * Events like `RewardRateUpdated` + +
+ +
+ +Auto Delegate (Overwhelming Support Strategy) + +* **Address:** [`0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158`](https://etherscan.io/address/0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158) + +- **Purpose:** Implements the “Overwhelming Support” auto-delegation strategy. This contract casts votes on behalf of un-delegated or transferred stOBOL when proposals receive strong community support. This mechanism uses tokens that would otherwise not be available in governance to ensure uncontroversial proposals will meet quorum. + +* **What you can find onchain:** + * Parameters like `supportThreshold`, `subQuorumBips`, and `votingWindow` + * Proposals voted on by the strategy + * Vote power amounts cast + * Event logs showing execution activity + * Wallets or protocols interacting with auto-delegation logic + +
+ +## Learn more about... + +[token-utility.md](token-utility.md) +[staking-and-stobol.md](staking-and-stobol.md) +[token-distribution-and-liquidity.md](token-distribution-and-liquidity.md) +[token-holders-faq.md](token-holders-faq.md) +[tge-faq.md](tge-faq.md) diff --git a/versioned_docs/version-v1.4/community-and-governance/obol-token/staking-and-stobol.md b/versioned_docs/version-v1.4/community-and-governance/obol-token/staking-and-stobol.md new file mode 100644 index 0000000000..583b15ff6f --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/obol-token/staking-and-stobol.md @@ -0,0 +1,81 @@ +--- +description: "This page explains how OBOL staking works, the role of stOBOL, and what happens when tokens are delegated, transferred, or used in DeFi protocols. You can stake and unstake OBOL via stake.obol.org." +sidebar_label: "Staking & stOBOL" +slug: /community-and-governance/obol-token/staking-and-stobol +--- + +# Staking & stOBOL + +## Overview + +Staking allows OBOL token holders to participate in governance while earning rewards. When you stake OBOL, you receive a liquid staking token called stOBOL. This token is transferable, composable in DeFi, and earns staking rewards while maintaining governance power, as long as it remains in the same address that originally staked the OBOL Tokens. It represents a flexible and powerful tool to both support the network and engage in the broader ecosystem. + +stOBOL unlocks new opportunities for participation. It is yield-bearing, enables seamless governance engagement, and is expected to be increasingly integrated across DeFi platforms. If it is transferred elsewhere, direct delegation is removed and governance power is reassigned using a protective fallback strategy, preventing governance attacks. + +### To Recap + +* stOBOL is a liquid staking token received when you stake OBOL. +* It allows users to earn staking rewards which auto-compound while retaining governance power. +* stOBOL is fully transferable (ERC-20) and can be used in DeFi (e.g., as collateral). + +## Key Concepts + +| **Feature** | **OBOL** | **stOBOL** | +| ------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| **Governance voting** | ✅ (direct or delegated) | ✅ (only if kept on original staking address, otherwise governance power reallocated to default strategy) | +| **Transferable** | ✅ | ✅ | +| **Used in DeFi** | ✅ (less efficient, not yield-bearing) | ✅ (yield-bearing) | +| **Earns staking rewards** | ❌ | ✅ | + +## Delegation & Governance + +Governance power is fundamentally tied to the OBOL Token. When OBOL is staked, the governance power does not transfer to stOBOL itself but remains associated with the underlying staked OBOL. stOBOL serves as a representation of that staked position, surfacing its governance power **only while being held in the same address** that originally staked the OBOL. + +If stOBOL is transferred to another address or smart contract, governance power is not automatically preserved. Instead: + +* By default, the governance power is reassigned to the **Overwhelming Support** auto-delegate strategy. +* However, the receiving address or smart contract **can explicitly delegate** the voting power of its stOBOL to a delegate of choice, if such functionality is supported. + +This design ensures that governance power follows clear, transparent rules: + +* **No double-counting**: the OBOL held in the staking contract is not counted separately from the stOBOL in circulation. +* **No governance arbitrage**: someone cannot gain voting rights simply by borrowing or acquiring stOBOL without also controlling the original staking delegation. + +If stOBOL is used in DeFi protocols (e.g., as collateral on Morpho), governance power defaults to the Overwhelming Support strategy unless the protocol itself implements explicit delegation support for pooled stOBOL assets. + +## How the Overwhelming Support Strategy Works + +When a liquid staking token (like stOBOL) is transferred, any previous delegation is removed. To prevent this from harming quorum or enabling governance attacks, the system can route that voting power through an automatic fallback strategy. The first strategy implemented is called the "Overwhelming Support" strategy. This fallback strategy only casts votes using its accrued governance power **in favor** of a proposal when all the following conditions are met: + +* **Sub-quorum reached:** At least 66% of the quorum is already met by FOR votes (`subQuorumBips = 66%`). +* **High support threshold:** At least 90% of votes cast so far are FOR votes (`supportThreshold = 90%`). +* **Within final voting window:** The proposal is within \~2.5 days of its deadline (`votingWindow = 14400` blocks). + +If all three criteria are met, the strategy casts its voting power FOR the proposal. If not, it abstains. + +This ensures that fallback voting power (from transferred stOBOL) is only used to support proposals that already have overwhelming community backing. It avoids influencing contentious or split decisions, protecting governance neutrality and reducing capture risk. + +This model preserves network governance while allowing for stOBOL to flow through DeFi protocols. + +Other strategies can be proposed via governance. + +## Summary Flow + +1. OBOL is staked and stOBOL is minted to the staker’s address. +2. While stOBOL remains with the same address, governance power is retained and delegated as usual. +3. If stOBOL is transferred, governance power is removed and reassigned via the "Overwhelming Support" strategy. Other strategies can be proposed via governance. + +![](/img/gitbook/stOBOL_03.png) + +## Additional Notes + +* You can stake and unstake OBOL via [stake.obol.org](https://vote.obol.org/stake). +* Voting and delegation are managed at [vote.obol.org](https://vote.obol.org/). + +As the protocol evolves, new strategies or staking configurations may be introduced through DAO governance. Feedback from the community helps inform these decisions. + +Have questions? Join our [Discord](https://discord.gg/n6ebKsX46w) or visit the [Governance Forum](https://community.obol.org). + +*** + +_This page will evolve as more staking strategies and integrations are launched._ diff --git a/versioned_docs/version-v1.4/community-and-governance/obol-token/tge-faq.md b/versioned_docs/version-v1.4/community-and-governance/obol-token/tge-faq.md new file mode 100644 index 0000000000..dcb25eb8f8 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/obol-token/tge-faq.md @@ -0,0 +1,137 @@ +--- +sidebar_label: "TGE FAQ" +slug: /community-and-governance/obol-token/tge-faq +--- + +# TGE FAQ + +## Unlock and Listing + +
+ +How do I unlock my OBOL Tokens received in the Airdrop? + +Starting May 7th at 11:00 AM UTC, visit [**claim.obol.org**](https://claim.obol.org), click **“Unlock”**, and follow the steps. + +
+ +
+ +When is the official TGE date and time? + +The OBOL Token will be listed on exchanges for deposit, trading and withdrawals on May 7th, 2025 at 11:00 AM UTC + +
+ +
+ +Where will the OBOL Token be listed for trading? + +* **Binance**, **Bybit**, **Bitget**, **Gate.io**, **MEXC**, and others. + +- Check [CoinGecko](https://coingecko.com) or [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) for the most up-to-date list. + +
+ +
+ +What are the exact listing times on exchanges? + +* **Binance Alpha** – _May 7 at 10:00 AM UTC_ + +- **Binance Futures** – _May 7 at 10:30 AM UTC_ + +* **Bybit, Gate.io, Bitget, MEXC** – _May 7 at 11:00 AM UTC_ + +
+ +
+ +Where can I track the price of the OBOL Token? + +[CoinGecko](https://coingecko.com) and [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) + +
+ +
+ +Where can I buy the OBOL Token onchain? + +* A **Uniswap v3 pool** will be seeded with initial liquidity. + +- The contract address is [here](https://etherscan.io/address/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434). + +* Anyone can start a pool. Check live prices via **CoinGecko**, or **CoinMarketCap**. + +
+ +
+ +Are there any country restrictions for claiming or trading the OBOL Token? + +* Yes. Each venue has its own restrictions. + +- Unlocking OBOL Tokens received through the Airdrop is subject to the same geo restrictions as claiming. + +
+ +## **Token Supply & Distribution** + +
+ +What is the circulating supply at TGE? + +Approximately 19**%**. Full breakdown is on [CoinMarketCap](https://coinmarketcap.com/currencies/obol/). + +
+ +
+ +Why does Etherscan show 374M tokens instead of 500M? + +For legal and tax reasons, not all tokens are minted yet. + +
+ +
+ +How many tokens were allocated to CoinList, and how many unlock at TGE? + +Details available on the [**Coinlist Sale Page**](https://coinlist.co/obol). + +
+ +
+ +When were unclaimed airdrop tokens returned to the treasury? + +As approved by [**OIP-2**](https://community.obol.org/t/oip-2-unlock-obol-token/317), they were [returned](https://etherscan.io/tx/0x738b4c252bb4613b9945e3b6426ec4ee510c6cdb86027fe20d533c4799a3a331) on **May 2, 2025**. + +
+ +## **Unlocks & Vesting** + +
+ +Can CoinList participants claim at TGE? + +Yes, a portion of their tokens will unlock on May 7th at 11AM UTC per the [**Coinlist terms**](https://coinlist.co/obol). + +
+ +
+ +Will RAF1 tokens be available at TGE? + +RAF1 tokens will be distributed **shortly after TGE**. + +
+ +
+ +When will OBOL Token incentives be claimable? + +Starting May 12, 2025, incentives will be distributed weekly + +
+ diff --git a/versioned_docs/version-v1.4/community-and-governance/obol-token/token-distribution-and-liquidity.md b/versioned_docs/version-v1.4/community-and-governance/obol-token/token-distribution-and-liquidity.md new file mode 100644 index 0000000000..649045f286 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/obol-token/token-distribution-and-liquidity.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Distribution & Liquidity" +slug: /community-and-governance/obol-token/token-distribution-and-liquidity +--- + +# Token Distribution & Liquidity + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](https://docs.obol.org/community-and-governance/governance/raf)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.4/community-and-governance/obol-token/token-holders-faq.md b/versioned_docs/version-v1.4/community-and-governance/obol-token/token-holders-faq.md new file mode 100644 index 0000000000..430515da8c --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/obol-token/token-holders-faq.md @@ -0,0 +1,135 @@ +--- +description: "This page is designed to answer the most common questions from OBOL token holders, particularly those holding liquid OBOL or stOBOL." +sidebar_label: "Token Holders FAQ" +slug: /community-and-governance/obol-token/token-holders-faq +--- + +# Token Holders FAQ + +## General + +
+ +What is the OBOL token used for? + +OBOL is the governance token of the Obol Collective. It enables holders to participate in on-chain governance by voting directly or delegating their voting power to delegates. + +OBOL is also used in the [RAF](../governance/raf/), where token holders delegate to vote on which contributors should receive retroactive funding for valuable work. + +In addition, OBOL can be staked to receive stOBOL, a liquid token that accrues staking rewards and retains governance power as long as it remains in the staker’s wallet. This staking mechanism supports long-term alignment and decentralized ownership. + +Finally, both OBOL and stOBOL are being integrated into DeFi protocols, such as liquidity pools, lending platforms (e.g. Morpho), and restaking services (e.g. Eigenlayer, Symbiotic), with more utility expected over time as shaped by community governance. + +
+ +
+ +What is stOBOL? + +stOBOL is the liquid staking token received when you stake OBOL. It earns staking rewards and can be used in DeFi. Holding stOBOL in your wallet preserves your governance power. More info in [#staking-and-stobol](staking-and-stobol.md "mention") + +
+ +
+ +Where can I see OBOL price, supply, and markets? + +You can track OBOL on [CoinMarketCap](https://www.coingecko.com/en/coins/obol-2) or [Coingecko](https://coingecko.com). These pages include market data, supply information, and live price charts. + +
+ +## Delegation & Governance + +
+ +How do I delegate my OBOL tokens? + +You can delegate via [vote.obol.org](https://vote.obol.org/dao/delegates). Connect your wallet, choose a delegate, and confirm the delegation transaction. + +
+ +
+ +What happens if I stake OBOL? + +You receive stOBOL, which maintains your delegation as long as it stays in your wallet. Once transferred (e.g., to a DeFi protocol), you lose the individual delegation. Voting power is then routed via an [auto-delegation strategy](staking-and-stobol.md). + +
+ +
+ +Can I change my delegate? + +Yes, you can re-delegate at any time through the Collective Portal at [vote.obol.org](https://vote.obol.org) + +
+ +
+ +Does holding OBOL give me passive income? + +Not directly. Only staking OBOL (to receive auto-compounding stOBOL) allows you to earn rewards. + +
+ +## Staking & stOBOL + +
+ +How do I stake OBOL? + +Use [stake.obol.org](https://stake.obol.org) to stake. You’ll receive auto-compounding stOBOL in return. + +
+ +
+ +Can I transfer stOBOL? + +Yes, stOBOL is a fully transferable ERC-20 token. However, if you transfer it, your direct delegation is lost, and your governance power enters the auto-delegation pool. + +
+ +
+ +Where can I use stOBOL? + +stOBOL can be used in DeFi protocols (e.g., as collateral, in LPs, etc.). Integrations are ongoing and will be announced via Discord and Twitter. + +
+ +
+ +Can I unstake OBOL? + +Yes. You can return stOBOL to the staking contract at anytime without lockup to reclaim your OBOL. Unstaking and restaking interfaces are provided at [stake.obol.org](https://stake.obol.org). + +
+ +## Token Value & Utility + +
+ +What gives the OBOL token value? + +OBOL gains utility through governance rights, staking yield, and its use in DeFi. Long term, its value could be tied to the growth of the Obol Network, including fees, protocol usage, and TVL. + +
+ +
+ +Does OBOL accrue fees? + +Currently, OBOL does not accrue protocol revenue. However, the DAO may vote in the future to direct protocol revenue toward token holders or stakers. + +
+ +
+ +How can I stay up to date on OBOL news? + +Join our [Discord](https://discord.gg/obol), follow [@ObolNetwork](https://x.com/Obol_Collective), and check our [Forum](https://community.obol.org) for governance and integration updates. + +
+ +_This page is updated regularly. If your question isn’t listed, reach out via Discord or the Governance Forum._ diff --git a/versioned_docs/version-v1.4/community-and-governance/obol-token/token-utility.md b/versioned_docs/version-v1.4/community-and-governance/obol-token/token-utility.md new file mode 100644 index 0000000000..60dd9ce505 --- /dev/null +++ b/versioned_docs/version-v1.4/community-and-governance/obol-token/token-utility.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "Token Utility" +slug: /community-and-governance/obol-token/token-utility +--- + +# Token Utility + +## **Governance** + +OBOL Token holders delegate their voting power to delegates who participate in the Token House decision-making processes. This includes voting on proposals affecting the Obol Collective’s direction, upgrades, and funding allocations. Read more about the Token House [here](../governance/token-house.md). + +## **Obol Retroactive Funding (RAF)** + +Token holders delegate their voting power to Delegates, who vote on the projects eligible for retroactive funding. Read more about the Obol RAF [here](../governance/raf/). + +## **OBOL Token Staking** + +As per[ OIP-1](https://community.obol.org/t/oip-1-building-and-enabling-staking-for-the-obol-token/312), OBOL token holders will have the opportunity to stake their tokens, contributing to the security and stability of the Collective by preserving governance while earning rewards and being able to engage in DeFi. Staking involves depositing OBOL tokens in a vault (without lockup) that automatically delegates the Tokens if not done already. In return, stakers receive stOBOL, which automatically accrues OBOL Tokens as rewards as it's price vs OBOL increases. + +This staking program will be implemented in phases, allowing the community to gradually engage in and benefit from the system while reinforcing the decentralization of the Obol Collective. For the first six months, the total rewards will be 0.33% of the total supply, providing early participants with attractive rewards. After this period, the staking rewards may be adjusted based on governance proposals and market conditions. This structured rollout ensures a sustainable and rewarding staking experience while reinforcing the decentralization of the Obol Collective. + +To get started, simply visit [https://stake.obol.org](https://stake.obol.org) and follow the staking flow — no technical setup required. The interface will guide you through selecting your wallet, choosing the amount to stake, and submitting the transaction. + +**You will find more info about the OBOL token staking in the dedicated** [staking-and-stobol.md](staking-and-stobol.md "mention") **section.** + +## **DeFi** + +Plans are in place to launch several DeFi avenues for the OBOL Token post-TGE, such as liquidity pools, lending protocols (e.g. Morpho) and restaking (e.g. Eigenlayer, Symbiotic). + +## **More Utility Coming Soon** + +Via Token House governance proposals in the [Governance Forum](https://community.obol.org/), the Obol community can add more functionality and utility to the OBOL Token. diff --git a/versioned_docs/version-v1.4/learn/charon/README.md b/versioned_docs/version-v1.4/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.4/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.4/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.4/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..c9116a4ceb --- /dev/null +++ b/versioned_docs/version-v1.4/learn/charon/charon-cli-reference.md @@ -0,0 +1,748 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.4.3`](https://github.com/ObolNetwork/charon/releases/tag/v1.4.3). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --target-gas-limit uint Preferred target gas limit for transactions. (default 36000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost (default "default") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH+ staked for each). (default 1) + --operator-addresses strings Comma-separated list of each operator's Ethereum address. + --operator-enrs strings Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + --publish Creates an invitation to the DKG ceremony on the DV Launchpad. Terms and conditions apply. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --target-gas-limit uint Preferred target gas limit for transactions. (default 36000000) + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 30s) + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 1m0s) +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --consensus-protocol string Preferred consensus protocol name for the node. Selected automatically when not specified. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + --graffiti strings Comma-separated list or single graffiti string to include in block proposals. List maps to validator's public key in cluster lock. Appends "OB" suffix to graffiti. Maximum 28 bytes per graffiti. + --graffiti-disable-client-append Disables appending "OB" suffix to graffiti. Increases maximum bytes per graffiti to 32. + -h, --help Help for run + --jaeger-address string [DISABLED] Listening address for jaeger tracing. + --jaeger-service string [DISABLED] Service name used for jaeger tracing. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --otlp-address string Listening address for OTLP gRPC tracing backend. + --otlp-service-name string Service name used for OTLP gRPC tracing. (default "charon") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its validator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 162304) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 162304) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default ".charon/cluster") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Test subcommands provide test suite to evaluate current cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [PingMeasure PingLoad DirectConn Ping Libp2pTCPPortOpen PingRelay PingMeasureRelay SimulateCustom Ping PingMeasure Synced PeerCount PingLoad Simulate1 Simulate10 Simulate100 Version Simulate500 Simulate1000 Ping PingMeasure PingLoad Ping PingMeasure CreateBlock DiskReadIOPS TotalMemory InternetDownloadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadSpeed AvailableMemory InternetLatency InternetUploadSpeed] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [PingLoad Simulate1 Simulate500 Ping Synced PeerCount Simulate10 Simulate100 Simulate1000 SimulateCustom PingMeasure Version] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [DiskWriteIOPS DiskReadSpeed AvailableMemory TotalMemory InternetDownloadSpeed InternetUploadSpeed DiskWriteSpeed DiskReadIOPS InternetLatency] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure CreateBlock] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad DirectConn Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.4/learn/charon/charon-networking.md b/versioned_docs/version-v1.4/learn/charon/charon-networking.md new file mode 100644 index 0000000000..acf16157fe --- /dev/null +++ b/versioned_docs/version-v1.4/learn/charon/charon-networking.md @@ -0,0 +1,83 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview[​](https://docs.obol.org/learn/charon/networking#overview) {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](https://docs.obol.org/learn/charon/networking#internal-validator-stack) and the [_external p2p network_](https://docs.obol.org/learn/charon/networking#external-p2p-network). + +### Internal Validator Stack[​](https://docs.obol.org/learn/charon/networking#internal-validator-stack) {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network[​](https://docs.obol.org/learn/charon/networking#external-p2p-network) {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](https://docs.obol.org/learn/charon/charon-cli-reference): + +* `--p2p-tcp-addresses`: Addresses for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security[​](https://docs.obol.org/learn/charon/networking#libp2p-authentication-and-security) {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](https://docs.obol.org/learn/charon/cluster-configuration#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p’s Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery[​](https://docs.obol.org/learn/charon/networking#libp2p-relays-and-peer-discovery) {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\ + + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters[​](https://docs.obol.org/learn/charon/networking#scalable-relay-clusters) {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URls. diff --git a/versioned_docs/version-v1.4/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.4/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..babea8e6e0 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralized backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long term decentralization of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definiition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.4/learn/charon/dkg.md b/versioned_docs/version-v1.4/learn/charon/dkg.md new file mode 100644 index 0000000000..6024f9a93e --- /dev/null +++ b/versioned_docs/version-v1.4/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENRs nonce and resign with the clients private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participants old keys out of a distributed validator in favor of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.4/learn/charon/intro.md b/versioned_docs/version-v1.4/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.4/learn/further-reading/README.md b/versioned_docs/version-v1.4/learn/further-reading/README.md new file mode 100644 index 0000000000..6f13128d79 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/further-reading/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading + diff --git a/versioned_docs/version-v1.4/learn/further-reading/community-testing.md b/versioned_docs/version-v1.4/learn/further-reading/community-testing.md new file mode 100644 index 0000000000..91ebf1cfde --- /dev/null +++ b/versioned_docs/version-v1.4/learn/further-reading/community-testing.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community Testing" +slug: /learn/further-reading/community-testing +--- + +# Community Testing + diff --git a/versioned_docs/version-v1.4/learn/further-reading/ethereum-and-its-relationship-with-dvt.md b/versioned_docs/version-v1.4/learn/further-reading/ethereum-and-its-relationship-with-dvt.md new file mode 100644 index 0000000000..52001d8401 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/further-reading/ethereum-and-its-relationship-with-dvt.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum-and-its-relationship-with-dvt +--- + +# Ethereum and Its Relationship With DVT + diff --git a/versioned_docs/version-v1.4/learn/further-reading/peer-score.md b/versioned_docs/version-v1.4/learn/further-reading/peer-score.md new file mode 100644 index 0000000000..7d232ebfa1 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/further-reading/peer-score.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer-score +--- + +# Peer Score + diff --git a/versioned_docs/version-v1.4/learn/further-reading/useful-links.md b/versioned_docs/version-v1.4/learn/further-reading/useful-links.md new file mode 100644 index 0000000000..627e249966 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/further-reading/useful-links.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Useful Links" +slug: /learn/further-reading/useful-links +--- + +# Useful Links + diff --git a/versioned_docs/version-v1.4/learn/futher-reading/README.md b/versioned_docs/version-v1.4/learn/futher-reading/README.md new file mode 100644 index 0000000000..09911677f3 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/futher-reading/README.md @@ -0,0 +1,8 @@ +--- +sidebar_label: "Futher Reading" +slug: /learn/futher-reading/futher-reading +unlisted: true +--- + +# Futher Reading + diff --git a/versioned_docs/version-v1.4/learn/futher-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.4/learn/futher-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..577e2b0347 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/futher-reading/ethereum_and_dvt.md @@ -0,0 +1,56 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/futher-reading/ethereum_and_dvt +unlisted: true +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.4/learn/futher-reading/peer_score.md b/versioned_docs/version-v1.4/learn/futher-reading/peer_score.md new file mode 100644 index 0000000000..f7520d399a --- /dev/null +++ b/versioned_docs/version-v1.4/learn/futher-reading/peer_score.md @@ -0,0 +1,49 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/futher-reading/peer_score +unlisted: true +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of a rated network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.4/learn/futher-reading/resources.md b/versioned_docs/version-v1.4/learn/futher-reading/resources.md new file mode 100644 index 0000000000..0a9b60f1c8 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/futher-reading/resources.md @@ -0,0 +1,60 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/futher-reading/resources +unlisted: true +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.4/learn/futher-reading/testnet.md b/versioned_docs/version-v1.4/learn/futher-reading/testnet.md new file mode 100644 index 0000000000..9244762697 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/futher-reading/testnet.md @@ -0,0 +1,191 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/futher-reading/testnet +unlisted: true +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.4/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.4/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..2a5ef8cad6 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/readme/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General[​](https://docs.obol.org/learn/intro/faq#general) {#general} +#### Does Obol have a token?[​](https://docs.obol.org/learn/intro/faq#does-obol-have-a-token) {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/obol-token/) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is 0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7. + +#### Where can I learn more about Distributed Validators?[​](https://docs.obol.org/learn/intro/faq#where-can-i-learn-more-about-distributed-validators) {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from?[​](https://docs.obol.org/learn/intro/faq#where-does-the-name-charon-come-from) {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node?[​](https://docs.obol.org/learn/intro/faq#what-are-the-hardware-requirements-for-running-a-charon-node) {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster?[​](https://docs.obol.org/learn/intro/faq#what-is-the-difference-between-a-node-a-validator-and-a-cluster) {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine?[​](https://docs.obol.org/learn/intro/faq#can-i-migrate-an-existing-charon-node-to-a-new-machine) {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation[​](https://docs.obol.org/learn/intro/faq#distributed-key-generation) {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator?[​](https://docs.obol.org/learn/intro/faq#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator) {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum numbers of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-threshold). + +### Obol Splits[​](https://docs.obol.org/learn/intro/faq#obol-splits) {#obol-splits} +#### What are Obol Splits?[​](https://docs.obol.org/learn/intro/faq#what-are-obol-splits) {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in future a number of other LSPs. + +#### Are Obol Splits non-custodial?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-non-custodial) {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split?[​](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split) {#can-i-change-the-percentages-in-a-split} +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work?[​](https://docs.obol.org/learn/intro/faq#how-do-obol-splits-work) {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](https://docs.obol.org/learn/intro/obol-splits). + +#### Are Obol Splits open source?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-open-source) {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-audited) {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](https://docs.obol.org/adv/security/smart_contract_audit). + +#### Are the Obol Splits contracts verified on Etherscan?[​](https://docs.obol.org/learn/intro/faq#are-the-obol-splits-contracts-verified-on-etherscan) {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts?[​](https://docs.obol.org/learn/intro/faq#does-my-cold-wallet-have-to-call-the-obol-splits-contracts) {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits?[​](https://docs.obol.org/learn/intro/faq#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits) {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst case mass slashing on the network. Consult the documentation on the contract [here](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient), its audit [here](https://docs.obol.org/adv/security/smart_contract_audit), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs[​](https://docs.obol.org/learn/intro/faq#debugging-errors-in-logs) {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](https://docs.obol.org/adv/troubleshooting/errors). diff --git a/versioned_docs/version-v1.4/learn/intro/key-concepts.md b/versioned_docs/version-v1.4/learn/intro/key-concepts.md new file mode 100644 index 0000000000..6ff0d5b5d4 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/key-concepts.md @@ -0,0 +1,112 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/readme/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimizing downtime in mission critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specializes in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof of stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys, that together operate as a threshold key for participating in proof of stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that needs to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 4 | 3/4 | Minimum threshold | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.4/learn/intro/launchpad.md b/versioned_docs/version-v1.4/learn/intro/launchpad.md new file mode 100644 index 0000000000..5a44a8cd53 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/launchpad.md @@ -0,0 +1,46 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/readme/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~** Staking Launchpad**](https://launchpad.ethereum.org/), a public good open source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +| ---------------- | -------------------------------------------------------------------------------- | +| Mainnet | [https://launchpad.obol.org](https://launchpad.obol.org) | +| Gnosis Chain | [https://gnosischain.launchpad.obol.org](https://gnosischain.launchpad.obol.org) | +| Holesky | [https://holesky.launchpad.obol.org](https://holesky.launchpad.obol.org) | +| Sepolia | [https://sepolia.launchpad.obol.org](https://sepolia.launchpad.obol.org) | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +## Use the Explorer + +Clicking "explore" on the top right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.4/learn/intro/obol-collective.md b/versioned_docs/version-v1.4/learn/intro/obol-collective.md new file mode 100644 index 0000000000..ebfe888368 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/readme/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +The Obol Collective is the largest Decentralized Operator Ecosystem. We provides the technology, opportunities, and community to scale decentralized infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs retroactive funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../futher-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](https://docs.obol.org/api), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.4/learn/intro/obol-incentives.md b/versioned_docs/version-v1.4/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..5892ed84b9 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/obol-incentives.md @@ -0,0 +1,180 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/readme/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible starting **May 12th, 2025.** + + + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at anytime but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.gg/obol](https://discord.gg/obol). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | diff --git a/versioned_docs/version-v1.4/learn/intro/obol-splits.md b/versioned_docs/version-v1.4/learn/intro/obol-splits.md new file mode 100644 index 0000000000..3243a9e797 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/obol-splits.md @@ -0,0 +1,122 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/readme/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators and their surrounding ecosystem of decentralised infrastructure. These contracts include: + +* Reward Splitting contracts: Contracts to split ether (and tokens) across multiple entities. Developed by [Splits.org](https://splits.org/) + +Key Design Principles the Obol Smart Contract suite include are: + +- That they are secure. All [released](https://github.com/ObolNetwork/obol-splits/releases/) Obol Splits products are [audited by high quality security teams](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments). +- They are not upgradeable. +- They are self-soverign. Any permissioned actions, such as withdrawal, exit, or operator rotation, are controlled by the user, not an unaccountable set of third parties with the ability to upgrade your contracts behaviour. +- They do not require a token to function. +- They are oracle-free. (Unless you intend to leverage a [swapper](https://docs.splits.org/core/swapper)). +- They divide the reward ether from principal ether such that staking providers can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal and reward_. +- That rewards can be withdrawn in an ongoing manner without exiting the validator. (Some conditions apply). + +## Optimistic Withdrawal Recipient[​](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient) {#optimistic-withdrawal-recipient} +![](/img/gitbook/image-15-1-1.png) + +Optimistic Withdrawal Recipients (OWRs) **are the predecessor to Obol Validator Managers**. The primary addition with Validator Managers is the role-based control over validator withdrawals, exits and consolidations. + +Optimistic Withdrawal Recipients allow for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use an splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + + + +## Split Contracts[​](https://docs.obol.org/learn/intro/obol-splits#split-contracts) {#split-contracts} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Validator Managers focus on the former, split contracts focus on the latter. They are best used in tandem. + +![Obol Validator Manager in Tandem with an Execution Layer Fee recipient splitter contract](/img/gitbook/ovm_splits_overview.png) + +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers[​](https://docs.obol.org/learn/intro/obol-splits#split-controllers) {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. We recommend using a [SAFE wallet](https://safe.global) to manage the Split. + +#### (Gnosis) SAFE wallet[​](https://docs.obol.org/learn/intro/obol-splits#gnosis-safe-wallet) {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administrate an editable split. The most well-known deployment of this pattern is the [protocol guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + + +## Deployments + +### Obol Lido Split Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#ols-factory-deployment) + +The `ObolLidoSplit` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/lido/ObolLidoSplitFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [](https://etherscan.io/address/) | +| Hoodi | [0xb633CD420aF83E8A5172e299104842b63dd97ab7](https://hoodi.etherscan.io/address/0xb633CD420aF83E8A5172e299104842b63dd97ab7) | +| Holesky | [](https://holesky.etherscan.io/address/) | +| Sepolia | [](https://sepolia.etherscan.io/address/) | + + +### OWR Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#owr-factory-deployment) + +The `OptimisticWithdrawalRecipient` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Holesky | [0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df](https://holesky.etherscan.io/address/0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | + + +## FAQ + +### What are Obol Splits? + +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido with Obol Lido Splits, and Native Staking with Obol Validator Managers. + +### Are Obol Splits non-custodial? + +Yes. Unless you were to decide to [deploy an editable splitter contract](#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. Obol Validator Managers have owners and Role Based Access Control, but these are self-sovereign and up to the deployer to set and manage. There is no third party with access to or control of your validator unless you grant them such access. + +### Can I change the percentages in a split? + +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a *controllable* splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html#). + +### Are Obol Splits open source? + +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +### Are Obol Splits audited? + +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments) and always deploy contracts only from published [releases](https://github.com/ObolNetwork/obol-splits/releases). + +### Are the Obol Splits contracts verified on Etherscan? + +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +### Does my cold wallet have to call the Obol Splits contracts? + +No. Any address can trigger the contracts to distribute the withdrawn/skimmed ether, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +### Are there any edge cases I should be aware of when using Obol Splits? + +The most important thing to be aware of is what address is the owner of the Obol Validator Manager, whether it has assigned any other addresses any roles, and whether or not the Split contract you are using has been set up with editability and by which address. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is to use a high threshold multi-sign like a SAFE as the `owner`/`controller`, or to renounce ownership and control entirely, and if in future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst case mass slashing on the network. Consult the documentation on the contract [here](../../learn/intro/obol-splits.md#optimistic-withdrawal-recipient), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. diff --git a/versioned_docs/version-v1.4/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.4/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..becb3a6d90 --- /dev/null +++ b/versioned_docs/version-v1.4/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/readme/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and PKI + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.4/run-a-dv/integrations/README.md b/versioned_docs/version-v1.4/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..77e5bf9a25 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# integrations + diff --git a/versioned_docs/version-v1.4/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.4/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..b7b9b507a4 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,58 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) and other applications. + +### Pre-requisites[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#pre-requisites) {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](https://docs.obol.org/next/adv/advanced/quickstart-sdk) is required. + +### Create a SAFE to own the EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-safe-to-own-the-eigenpod) {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-an-eigenpod) {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-splitter-for-the-block-reward) {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-the-dv-cluster-invite) {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](https://docs.obol.org/next/run/start/quickstart_group) on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](https://docs.obol.org/next/run/integrations/quickstart-sdk) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#deposit-and-restake-your-distributed-validator) {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. + diff --git a/versioned_docs/version-v1.4/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.4/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..916487a37a --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/integrations/dappnode.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# DappNode + +For setup, see quickstart guide:[​](https://docs.obol.org/next/run/integrations/Dappnode#for-setup-see-quickstart-guide) + +For setup of a DV using Dappnode, see the quickstart guide [Create a DV Alone](https://docs.obol.org/next/run/start/quickstart_alone), and select the appropriate tab for "Dappnode". + +### Frequently asked questions[​](https://docs.obol.org/next/run/integrations/Dappnode#frequently-asked-questions) {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster?[​](https://docs.obol.org/next/run/integrations/Dappnode#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-the-validator-and-charon-volumes-to-use-the-same-enr-for-another-cluster) {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image-3.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC?[​](https://docs.obol.org/next/run/integrations/Dappnode#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag-for-lodestar-vc) {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically.\\ + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol?[​](https://docs.obol.org/next/run/integrations/Dappnode#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-same-dappnode-machine-push-monitoring-data-from-both-clusters-to-obol) {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.4/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.4/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..9e7163760e --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,226 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://operatorportal.lido.fi/modules/community-staking-module) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from Holesky just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using CSM UI in advanced mode, using the `extendedManagerPermissions` to set the `managerAddress` to the cluster multi-sig (SAFE) and the `rewardAddress` to the Splits.org splitting contract. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (if members want to use a distinct address to the one they sign with for receiving rewards). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (reccommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol’s '[1% for Decentralisation](https://blog.obol.org/1-percent-for-decentralisation/)' Retroactive Fund, thereby earning [Obol Contributions](https://obol.org/contributions) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [retroactivefunding.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol's RAF. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated a CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create up to 12 validator keys (CSM's Early Access limit) with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create. +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using you favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM is launching with a whitelisted set of approved operators (Early Access). The squad member with EA should be the one to create the node through the CSM widget. + +The EA member will head to [CSM Extended Mode](https://csm.lido.fi/?mode=extended) and connect their wallet. (Note the `mode=extended` parameter.) This allows the Lido CSM reward address to be set to the split contract created earlier. + +![](/img/gitbook/image-47.png) + +The EA member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The EA member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The EA member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button.\ + + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.4/run-a-dv/prepare/README.md b/versioned_docs/version-v1.4/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..6d77f77e82 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# prepare + diff --git a/versioned_docs/version-v1.4/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.4/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..09f03f65be --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,99 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10mb/s internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25mb/s internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimize both performance and cost-effectiveness, it is recommended to prioritize physical over virtualized setups. Such configurations typically offer greater performance and minimize overhead associated with virtualization, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimize Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimize potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes would potentially impact the fault tolerance of the cluster and as a result should be avoided. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. Be sure to use encrypted communication between your VC and the Charon client, potentially through a cloud-provided network, a self-managed network tunnel, a VPN, a Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), or other manner. + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration/#cluster-size-and-resilience)). + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](./test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +The clusters should consist of a combination of your preferred consensus, execution, and validator clients. It is recommended to include a combination of multiple clients in order to have a healthy client diversity within the cluster, ideally, if any single client type fails, it should be less than the fault tolerance of the cluster, and the validators should stay online/not do anything slashable. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Metrics Monitoring + +As requested by Obol Labs, node operators can push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. Our recommendation for operators is to independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (usually < 24 hours). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.4/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.4/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..6988ffd3b2 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatability information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.4/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.4/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..a8e28714f8 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,483 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + + + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the beacon node and validator client tests, you need to point them toward the correct Docker container, and also include the Docker container’s network. Check your docker networks with `docker network ls`. When you run the test command, specify the Docker network with `--network `. Read more about docker networking [here](https://docs.docker.com/engine/network/). + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.4.3 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.4.3 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.4.3 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.4.3 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.4.3 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.4.3 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +``` +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +``` +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + +#### Pre-requisites + +The storage tests require `fio` to be installed on your machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +#### Example run + +```sh +charon alpha test infra +``` diff --git a/versioned_docs/version-v1.4/run-a-dv/running/README.md b/versioned_docs/version-v1.4/run-a-dv/running/README.md new file mode 100644 index 0000000000..515e6cbede --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# running + diff --git a/versioned_docs/version-v1.4/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.4/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..3c7cddf6d9 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +Use any of the following tools to deposit. Please use the third-party tools at your own risk and always double check the staking contract address. + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. diff --git a/versioned_docs/version-v1.4/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.4/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..3d4aa06850 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/running/claim-rewards.md @@ -0,0 +1,66 @@ +--- +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +Introduction[​](https://docs.obol.org/next/run/running/claim-rewards#introduction) + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator’s withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +The method for claiming rewards depends on the Cluster's withdrawal configuration, whether it's an [**OWR**](https://docs.obol.org/next/learn/intro/obol-splits#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](https://docs.obol.org/next/learn/intro/obol-splits#exitable-withdrawal-recipient) . The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +\ + + +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](https://docs.obol.org/run/integrations/lido-csm). | + +### Claim Flow[​](https://docs.obol.org/next/run/running/claim-rewards#claim-flow) {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](https://docs.obol.org/next/learn/intro/obol-splits). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +1. All validator rewards are accumulated in the validator's withdrawal address, which is a split wallet. +2. Claims can be triggered in two ways: + 1. **From addresses in the Splitter**: Splitter addresses will see a `Claim All` button. When the first address (e.g., address A) executes `Claim All`, it triggers a multi-call transaction to distribute rewards from all the split wallets associated with a cluster into the Split Main. The Split Main then sends address A’s proportion of the rewards (based on the split configuration at the time of cluster creation). All of this is executed with a single click for the first address. + 2. **From addresses not in the Splitter**: Non-splitter addresses will see a `Distribute All` button instead of `Claim All`. These addresses cannot claim rewards directly but can distribute rewards to the Split Main (subsidizing transaction fees for others). Operators can then claim rewards later by visiting the same cluster details page. +3. Internally, after clicking `Claim All` or `Distribute All`, the split wallet sends the funds to the Split Main contract. +4. The Split Main then sends proportional rewards to **address A**, completing steps 2a, 3, and 4 with a single click. +5. Other addresses (e.g., B, C, D) can later click on `Claim All` to receive their share of the rewards. + +### Launchpad Edge Cases[​](https://docs.obol.org/next/run/running/claim-rewards#launchpad-edge-cases) {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: The `Claimable` column doesn’t match the amount next to the `Claim All` button. {#case-1-the-claimable-column-doesnt-match-the-amount-next-to-the-claim-all-button} +![](/img/gitbook/image-87.png) + +![](/img/gitbook/image-1-1-1-1-1.png) + +In this scenario, someone else (a splitter or non-splitter address) has already distributed rewards to the Split Main (e.g., 0.12 ETH). However, your validators (4 in this case) have earned an additional 0.2 ETH in rewards. Your total effective claimable balance is 0.032 ETH, which you can claim using the `Claim All` button. + +:::info +Your total effective claimable amount will always be displayed next to the `Claim All` button. +::: + +#### Case 2: You don’t see a `Claim All` button but instead see `Distribute All`.[​](https://docs.obol.org/next/run/running/claim-rewards#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all) {#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all} +![](/img/gitbook/image-88.png) + +This happens because the connected address is not listed in the split configuration. You may have used a different operator address from the one in the splitter configuration. You can: + +* Distribute all rewards using the connected address for all operators and claim using your address in the splitter configuration. +* Switch to the splitter address and claim directly. + +Note: It costs the same gas to distribute rewards for one address as it does for all addresses. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows a `Claim All` amount. {#case-3-you-just-created-a-new-cluster-with-no-active-validators-or-rewards-but-it-shows-a-claim-all} +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all `Claim All` buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.4/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.4/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..8b1d75ea57 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,933 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction[​](https://docs.obol.org/next/run/running/quickstart-exit#introduction) {#introduction} +Users looking to exit staking entirely and withdraw their full balance back must sign and broadcast a "voluntary exit" message with validator keys which will start the process of exiting from staking. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proporiton of principal and rewards. + +There are two ways to sign the partial exit and broadcast the full exit. Both the solutions don't require gas. + +1. **Using the Charon’s exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via launchpad and ability to download partial exits and broadcast them later as required. Users don’t have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use launchpad to monitor exit status and will have to use grafana to query the partial exit status. + +:::info +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +As per your preferences, choose the correct combination of - + +1. **Network** : Mainnet or Holesky +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quanity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +#### Step 1: Submit partial exit {#introduction} + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message.\\ + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](https://docs.obol.org/img/PartialExitsStatus.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch[​](https://docs.obol.org/next/run/running/quickstart-exit#exit-epoch-and-withdrawable-epoch) {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.4/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.4/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..df986f4233 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/running/monitoring.md @@ -0,0 +1,90 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/d6qujIJVk/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show following page. Choose Discord in the `Integration` drop down.\ + + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md). + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.4/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.4/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..c33e9bd637 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,124 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimse liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimse liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + diff --git a/versioned_docs/version-v1.4/run-a-dv/start/README.md b/versioned_docs/version-v1.4/run-a-dv/start/README.md new file mode 100644 index 0000000000..f8e137e70b --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# start + diff --git a/versioned_docs/version-v1.4/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.4/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..ee754c49d1 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,215 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](https://docs.obol.org/run/start/quickstart_group) instead for this latter case. +::: + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_alone#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.4.3 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 create cluster \ + --nodes=6 \ + --network=holesky \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](https://docs.obol.org/next/run/start/quickstart_alone#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately.\ +\ +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Holesky testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Setup the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample.holesky .env +``` +::: + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.4/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.4/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..058bc4fdae --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,618 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_group#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](https://docs.obol.org/next/run/prepare/deployment-best-practices#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](https://docs.obol.org/next/adv/troubleshooting/errors#docker-permission-denied-error) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client**[**​**](https://docs.obol.org/next/run/start/quickstart_group#prepare-an-execution-and-consensus-client) + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package**[**​**](https://docs.obol.org/next/run/start/quickstart_group#install-the-obol-dappnode-package) + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will be see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge**[**​**](http://localhost:3000/run/start/quickstart_group#installing-sedge) + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful**[**​**](http://localhost:3000/run/start/quickstart_group#check-the-install-was-successful) + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +#### Collect addresses, configure the cluster, share the invitation + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + 1. Select the desired amount of validators (32 ETH each) the cluster will run. (Note that the mainnet launchpad is restricted to one validator for now.) + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr) in the "What is your charon client's ENR?" field. + 3. Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. + 4. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions of participating as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +#### Join the cluster prepared by the creator + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address provided to the leader.\ + + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue.\ + + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr).\\ + + ![](/img/gitbook/image-83.png) +6. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +7. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](https://docs.obol.org/next/learn/charon/dkg) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) \\ + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. \\ + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.4.3 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run.\\ + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page.\\ + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +#### Create a DV Node Backup + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present.\\ + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long term. + + + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose, further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Holesky testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +````sh +# To prepare the node for the Holesky test network +# Copy ".env.sample.holesky", renaming it ".env" +cp .env.sample.holesky .env + + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env + + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```shell + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +```` + +:::warning +Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. +::: + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/d6qujIJVk/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). + + + +To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-generate) + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Holesky network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=holesky --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-import-key) + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ holesky teku +``` + +**Sedge Run**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-run) + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. + + + +Use an ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. + + + +Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. + + + +Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. + + + + + +:::warning +Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. +::: + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Copy the `docker-compose.override.yml.sample` file + +```sh +cp -n docker-compose.override.yml.sample docker-compose.override.yml +``` + +2. Uncomment the `profiles: [disable]` section for both `nethermind` and `lighthouse`. The override file should now look like this + +``` +services: + nethermind: + # Disable nethermind + profiles: [disable] + # Bind nethermind internal ports to host ports + #ports: + #- 8545:8545 # JSON-RPC + #- 8551:8551 # AUTH-RPC + #- 6060:6060 # Metrics + lighthouse: + # Disable lighthouse + profiles: [disable] + # Bind lighthouse internal ports to host ports + #ports: + #- 5052:5052 # HTTP + #- 5054:5054 # Metrics +... +``` + +3. Then, uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +4. Restart your docker compose + +```sh +docker compose down +docker compose up -d +``` + + + +:::tip +In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is `:3610`. Read more about Charon's networking [here](https://docs.obol.org/next/learn/charon/networking). +::: + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](https://docs.obol.org/next/run/running/activate-dv) to begin staking. diff --git a/versioned_docs/version-v1.4/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.4/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..8aa5fff0de --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,56 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics to Obol Monitoring" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics to Obol Monitoring + +:::info +This is **optional** and does not confer any special privileges within the Obol Network. +::: + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](http://localhost:3000/run/start/quickstart_overview), and have been provided with **Monitoring Credentials** used to push distributed validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve your Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +#### Update the monitoring token in the `.env` file + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +#### Save the `.env` file and restart Prometheus + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab.\\ + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it.\\ + + ![](/img/gitbook/image-86.png) + + diff --git a/versioned_docs/version-v1.4/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.4/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..be7af33fc1 --- /dev/null +++ b/versioned_docs/version-v1.4/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to utilize Distributed Validators for solo or multi-operator staking. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](./create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](./create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.4/sdk/classes/Client.md b/versioned_docs/version-v1.4/sdk/classes/Client.md new file mode 100644 index 0000000000..a19a70f5e8 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/classes/Client.md @@ -0,0 +1,244 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +### Extends + +* `Base` + +### Constructors + +#### new Client() + +> **new Client**(`config`, `signer`?): [`Client`](Client.md) + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | -------- | --------------------- | +| `config` | `object` | Client configurations | +| `config.baseUrl`? | `string` | obol-api url | +| `config.chainId`? | `number` | Blockchain network ID | +| `signer`? | `Signer` | ethersJS Signer | + +**Returns** + +[`Client`](Client.md) + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client: [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +**Overrides** + +`Base.constructor` + +**Defined in** + +index.ts:66 + +### Methods + +#### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`<`string`> + +Accepts Obol terms and conditions to be able to create or update data. + +**Returns** + +`Promise`<`string`> + +terms and conditions acceptance success message. + +**Throws** + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions: [acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +**Defined in** + +index.ts:79 + +*** + +#### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys OWR and Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| --------------------- | ------------------------------------------------------------- | --------------------------------------- | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit: [createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:133 + +*** + +#### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| ------------------- | ----------------------------------------------------------- | -------------------------------------------------- | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit: [createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:254 + +*** + +#### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`<`string`> + +Creates a cluster definition which contains cluster configuration. + +**Parameters** + +| Parameter | Type | Description | +| ------------ | ----------------------------------------------------- | ----------------------- | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +**Returns** + +`Promise`<`string`> + +config\_hash. + +**Throws** + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition: [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +**Defined in** + +index.ts:350 + +*** + +#### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Approves joining a cluster with specific configuration. + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition. + +**Throws** + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition: [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +**Defined in** + +index.ts:415 + +*** + +#### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | ---------------------------------------------------------- | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition for config hash + +**Throws** + +On not found config hash. + +An example of how to use getClusterDefinition: [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +**Defined in** + +index.ts:469 + +*** + +#### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | -------------------------------------------- | +| `configHash` | `string` | The configuration hash in cluster-definition | + +**Returns** + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +**Throws** + +On not found cluster definition or lock. + +An example of how to use getClusterLock: [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +**Defined in** + +index.ts:488 diff --git a/versioned_docs/version-v1.4/sdk/classes/README.md b/versioned_docs/version-v1.4/sdk/classes/README.md new file mode 100644 index 0000000000..d71a58615e --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# classes + diff --git a/versioned_docs/version-v1.4/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.4/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..7dda512eb1 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,15 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `0x00000000` | `1` | Mainnet. | types.ts:6 | +| `0x00001020` | `5` | Goerli/Prater. | types.ts:9 | +| `0x00000064` | `100` | Gnosis Chain. | types.ts:12 | +| `0x01017000` | `17000` | Holesky. | types.ts:15 | diff --git a/versioned_docs/version-v1.4/sdk/enumerations/README.md b/versioned_docs/version-v1.4/sdk/enumerations/README.md new file mode 100644 index 0000000000..5069f1f6ed --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# enumerations + diff --git a/versioned_docs/version-v1.4/sdk/functions/README.md b/versioned_docs/version-v1.4/sdk/functions/README.md new file mode 100644 index 0000000000..62be7a3a85 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# functions + diff --git a/versioned_docs/version-v1.4/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.4/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..cb920b4b8b --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/functions/validateClusterLock.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock + +> **validateClusterLock**(`lock`): `Promise`<`boolean`> + +Verifies Cluster Lock's validity. + +### Parameters + +| Parameter | Type | Description | +| --------- | ----------------------------------------------- | ------------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | + +### Returns + +`Promise`<`boolean`> + +boolean result to indicate if lock is valid + +### Throws + +on missing keys or values. + +An example of how to use validateClusterLock: [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) + +### Defined in + +services.ts:13 diff --git a/versioned_docs/version-v1.4/sdk/index.md b/versioned_docs/version-v1.4/sdk/index.md new file mode 100644 index 0000000000..d22906b706 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/index.md @@ -0,0 +1,93 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + +# Intro + +**SDK Version:** v2.1.0 + +![Obol Logo](https://obol.org/obolnetwork.png) + +## Obol SDK + +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](https://docs.obol.org/api). + +### Getting Started + +Checkout our [docs](https://docs.obol.org/advanced/quickstart-sdk), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +### Terms and Conditions + +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +### ⚠️ Important Security Notice: + +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +* The private key is securely stored (e.g., in an `.env` file). +* Never commit or push your `.env` file containing the private key to version control. + +### Contributing + +Please review the following guidelines: + +* [How to Report Bugs](index.md#how-to-report-bugs) +* [How to Propose Changes](index.md#how-to-propose-changes) +* [Code Review Process](index.md#code-review-process) + +#### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +#### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +#### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +### Enumerations + +* [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +### Classes + +* [Client](classes/Client.md) + +### Interfaces + +* [ClusterDefinition](interfaces/ClusterDefinition.md) +* [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) + +### Type Aliases + +* [ClusterOperator](type-aliases/ClusterOperator.md) +* [OperatorPayload](type-aliases/OperatorPayload.md) +* [ClusterCreator](type-aliases/ClusterCreator.md) +* [ClusterValidator](type-aliases/ClusterValidator.md) +* [ClusterPayload](type-aliases/ClusterPayload.md) +* [SplitRecipient](type-aliases/SplitRecipient.md) +* [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +* [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +* [BuilderRegistration](type-aliases/BuilderRegistration.md) +* [DepositData](type-aliases/DepositData.md) +* [DistributedValidator](type-aliases/DistributedValidator.md) +* [ClusterLock](type-aliases/ClusterLock.md) +* [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) + +### Functions + +* [validateClusterLock](functions/validateClusterLock.md) diff --git a/versioned_docs/version-v1.4/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.4/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..b57096a0bf --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +Cluster definition data needed for dkg + +## Extends + +- [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | `ClusterPayload.name` | types.ts:73 | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)[] | The cluster nodes operators addresses. | `ClusterPayload.operators` | types.ts:76 | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)[] | The cluster validators information. | `ClusterPayload.validators` | types.ts:79 | +| `deposit_amounts?` | `null` \| `string`[] | The cluster partial deposits in gwei or 32000000000. | `ClusterPayload.deposit_amounts` | types.ts:82 | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | types.ts:90 | +| `version` | `string` | The cluster configuration version. | - | types.ts:93 | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | types.ts:96 | +| `fork_version` | `string` | The cluster fork version. | - | types.ts:99 | +| `uuid` | `string` | The cluster uuid. | - | types.ts:102 | +| `timestamp` | `string` | The cluster creation timestamp. | - | types.ts:105 | +| `config_hash` | `string` | The cluster configuration hash. | - | types.ts:108 | +| `threshold` | `number` | The distributed validator threshold. | - | types.ts:111 | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | types.ts:114 | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | types.ts:117 | diff --git a/versioned_docs/version-v1.4/sdk/interfaces/README.md b/versioned_docs/version-v1.4/sdk/interfaces/README.md new file mode 100644 index 0000000000..b635dbc6dc --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# interfaces + diff --git a/versioned_docs/version-v1.4/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.4/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..f52df5e475 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +OWR and Split Proxy Params + +## Extends + +- [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | types.ts:136 | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | types.ts:139 | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | types.ts:142 | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | types.ts:145 | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | types.ts:153 | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | types.ts:156 | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | types.ts:159 | diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.4/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..281cd48a13 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +> **BuilderRegistration**: `object` + +Pre-generated Signed Validator Builder Registration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | types.ts:184 | +| `signature` | `string` | BLS signature of the builder registration message. | types.ts:187 | + +## Defined in + +types.ts:182 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.4/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..f7467b4436 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +> **BuilderRegistrationMessage**: `object` + +Unsigned DV Builder Registration Message + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient` | `string` | The DV fee recipient. | types.ts:167 | +| `gas_limit` | `number` | Default is 30000000. | types.ts:170 | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | types.ts:173 | +| `pubkey` | `string` | The public key of the DV. | types.ts:176 | + +## Defined in + +types.ts:165 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..643f98978e --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +> **ClusterCreator**: `object` + +Cluster creator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The creator address. | types.ts:52 | +| `config_signature`? | `string` | The cluster configuration signature. | types.ts:54 | + +## Defined in + +types.ts:50 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..e386f0060e --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +> **ClusterLock**: `object` + +Cluster Details after DKG is complete + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | types.ts:235 | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)[] | The cluster distributed validators. | types.ts:238 | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | types.ts:241 | +| `lock_hash` | `string` | The hash of the cluster lock. | types.ts:244 | +| `node_signatures`? | `string`[] | Node Signature for the lock hash by the node secp256k1 key. | types.ts:247 | + +## Defined in + +types.ts:233 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..c12e7caa48 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +> **ClusterOperator**: `object` + +Node operator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The operator address. | types.ts:23 | +| `enr`? | `string` | The operator ethereum node record. | types.ts:26 | +| `fork_version`? | `string` | The cluster fork_version. | types.ts:29 | +| `version`? | `string` | The cluster version. | types.ts:32 | +| `enr_signature`? | `string` | The operator enr signature. | types.ts:35 | +| `config_signature`? | `string` | The operator configuration signature. | types.ts:38 | + +## Defined in + +types.ts:21 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..ab4d99aff2 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +> **ClusterPayload**: `object` + +Cluster configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | types.ts:73 | +| `operators` | [`ClusterOperator`](ClusterOperator.md)[] | The cluster nodes operators addresses. | types.ts:76 | +| `validators` | [`ClusterValidator`](ClusterValidator.md)[] | The cluster validators information. | types.ts:79 | +| `deposit_amounts`? | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | types.ts:82 | + +## Defined in + +types.ts:71 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..266d48a113 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +> **ClusterValidator**: `object` + +Validator withdrawal configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | types.ts:62 | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | types.ts:65 | + +## Defined in + +types.ts:60 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.4/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..592d2f643b --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +> **DepositData**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | The public key of the distributed validator. | types.ts:195 | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | types.ts:198 | +| `amount` | `string` | 32 ethers. | types.ts:201 | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | types.ts:204 | +| `signature` | `string` | BLS signature of the deposit message. | types.ts:207 | + +## Defined in + +types.ts:193 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.4/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..5ec5dcc09d --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +> **DistributedValidator**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | types.ts:215 | +| `public_shares` | `string`[] | The public key of the node distributed validator share. | types.ts:218 | +| `deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\> | The deposit data for activating the DV. | types.ts:221 | +| `partial_deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\>[] | The deposit data with partial amounts or full amount for activating the DV. | types.ts:224 | +| `builder_registration`? | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | types.ts:227 | + +## Defined in + +types.ts:213 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.4/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..c08cb82c83 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +> **ETH\_ADDRESS**: `string` + +String expected to be Ethereum Address + +## Defined in + +types.ts:253 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.4/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..ee7810452c --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +> **OperatorPayload**: `Partial`\<[`ClusterOperator`](ClusterOperator.md)\> & `Required`\<`Pick`\<[`ClusterOperator`](ClusterOperator.md), `"enr"` \| `"version"`\>\> + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. + +## Defined in + +types.ts:44 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/README.md b/versioned_docs/version-v1.4/sdk/type-aliases/README.md new file mode 100644 index 0000000000..9e1ac60271 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# type-aliases + diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.4/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..e40db01a6c --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +> **SplitRecipient**: `object` + +Split Recipient Keys + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `account` | `string` | The split recipient address. | types.ts:125 | +| `percentAllocation` | `number` | The recipient split. | types.ts:128 | + +## Defined in + +types.ts:123 diff --git a/versioned_docs/version-v1.4/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.4/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..12e45d2c89 --- /dev/null +++ b/versioned_docs/version-v1.4/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +> **TotalSplitPayload**: `object` + +Split Proxy Params + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)[] | The split recipients addresses and splits. | types.ts:136 | +| `ObolRAFSplit`? | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | types.ts:139 | +| `distributorFee`? | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | types.ts:142 | +| `controllerAddress`? | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | types.ts:145 | + +## Defined in + +types.ts:134 diff --git a/versioned_docs/version-v1.4/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.4/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..5368c6e179 --- /dev/null +++ b/versioned_docs/version-v1.4/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# walkthroughs + diff --git a/versioned_docs/version-v1.4/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.4/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.4/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_docs/version-v1.5/README.md b/versioned_docs/version-v1.5/README.md new file mode 100644 index 0000000000..1cf9800b4e --- /dev/null +++ b/versioned_docs/version-v1.5/README.md @@ -0,0 +1,8 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "Introduction" +slug: /learn/readme +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..27650c3586 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# advanced + diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..6b3411b426 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 `tempo`. 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 +``` diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/beacon-node-authentication.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/beacon-node-authentication.md new file mode 100644 index 0000000000..2155b6158e --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/beacon-node-authentication.md @@ -0,0 +1,39 @@ +--- +description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control." +sidebar_label: "Beacon node authentication" +slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication +--- + +# Beacon node authentication + +## HTTP Basic Access Authentication + +If you want to use Charon with a [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic ` where `Authorization`will be the header key and `Basic ` will be the header value. The `` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`. + +:::warning +These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node. +::: + +## Usage example + +Suppose we have a HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command: + +``` +echo -n "john:doe" | base64 +``` + +Then you could pass the flag to your Charon instance like this: + +``` +charon run --beacon-node-headers="Authorization=Basic am9objpkb2U=" +``` + +Or you could specify it as an environment variable like this: + +``` +CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U=" +``` + +:::info +Note that 'Authorization' is followed with an `=` rather than the usual `:`. +::: diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..cb8e916119 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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](https://docs.obol.org/next/learn/intro/launchpad). + +### Pre-requisites[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#pre-requisites) {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#install-the-package) {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#instantiate-the-client) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#propose-the-cluster) {#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. + +```sh +// 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#invite-the-operators-to-complete-the-dkg) {#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](https://docs.obol.org/next/learn/intro/launchpad) to complete the process + +1. Operators navigate to `https://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](https://docs.obol.org/next/run/start/quickstart_group) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#retrieve-the-created-distributed-validators-using-the-sdk) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#activate-the-dvs-using-the-deposit-contract) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#usage-examples) {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/custom-graffiti.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/custom-graffiti.md new file mode 100644 index 0000000000..df9d593d9f --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/custom-graffiti.md @@ -0,0 +1,16 @@ +--- +description: "Add custom graffiti to your block proposals" +sidebar_label: "Custom Graffiti" +slug: /advanced-and-troubleshooting/advanced/custom-graffiti +unlisted: true +--- + +# Custom Graffiti + +By default, Charon adds a `charon/-` graffiti to all block proposals. This can be customized using the `--graffiti` and `--graffiti-disable-client-append` CLI flags. + +The `--graffiti` flag accepts either: +- A single string, which will be used by all validators, or +- A comma-separated list of strings, allowing each validator to have a unique graffiti (one string per validator). + +Each graffiti has a maximum length of 28 bytes to leave room for Charon to append a suffix containing the Obol signature, `OB`, and the specific consensus client type used, ``. This behavior can be disabled by setting the `--graffiti-disable-client-append` flag which also increases the maximum graffiti length to 32 bytes. \ No newline at end of file diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..f7e0c6e6de --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#getting-started-with-charon--the-builder-api) {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#client-configuration) {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#charon) {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#consensus-clients) {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](https://docs.obol.org/next/run/prepare/test-command#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#validator-clients) {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#verify-your-cluster-is-correctly-configured) {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [Ultrasound Relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. If you are using [Titan Relay](https://titanrelay.xyz), you can check their API by running `curl https://titanrelay.xyz/relay/v1/data/validator_registration?pubkey=0x123..456` with the public key of a validator in your cluster. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/enable-tls-protocol.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/enable-tls-protocol.md new file mode 100644 index 0000000000..4aba48fa70 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/enable-tls-protocol.md @@ -0,0 +1,38 @@ +--- +description: "Enable the TLS protocol to secure HTTPS requests made by the Validator Client to Charon." +sidebar_label: "Enable TLS protocol" +slug: /advanced-and-troubleshooting/advanced/enable-tls-protocol +unlisted: true +--- + +# Enable TLS protocol + +## Securing VC to Charon communication + +To secure the communication between the Validator Client and Charon, you can enable the TLS protocol in Charon's HTTP server. This only affects [Beacon API](https://ethereum.github.io/beacon-APIs/) endpoints and not debug/metrics endpoints. As an operator of the node, you need to have a TLS certificate and a private key that signed this certificate or CSR. Then you need to configure Charon to use them. +## Usage example + +Suppose we don't have a TLS certificate and a key yet. We can create a self-signed certificate and a key using OpenSSL: + +``` +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +Then you could pass the flags to your Charon instance like this: + +``` +charon run --vc-tls-cert-file cert.pem --vc-tls-key-file key.pem +``` + +Charon accepts a certificate in PEM or CRT formats and the private key in PEM or DER formats. + +Also you can specify these parameters as environment variables like this: + +``` +CHARON_VC_TLS_CERT_FILE="cert.pem" +CHARON_VC_TLS_KEY_FILE="key.pem" +``` + +On the Validator Client (VC) side, no additional configuration is typically required. The VC will automatically use the TLS protocol when communicating with Charon. However, if the TLS certificate is signed by a custom or non-standard certificate authority (CA), you may need to configure the VC to trust this CA. This can usually be achieved by adding the CA's certificate to the trusted certificate store on the machine running the VC. + +If necessary, you can also enable `insecure` mode in the VC configuration to bypass TLS verification. Note that this approach is not recommended for production environments as it compromises security. Detailed instructions for configuring specific Validator Clients are beyond the scope of this article. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/fallback-beacon-node.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/fallback-beacon-node.md new file mode 100644 index 0000000000..c8a8306191 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/fallback-beacon-node.md @@ -0,0 +1,14 @@ +--- +description: "Add fallback beacon nodes to use when primary beacon node fails" +sidebar_label: "Fallback beacon nodes" +slug: /advanced-and-troubleshooting/advanced/fallback-beacon-node +unlisted: true +--- + +# Fallback beacon nodes + +Charon allows specifying multiple beacon node URL endpoints. It sends requests to all specified endpoints simultaneously and proceeds with the first response received. This approach improves reliability but increases the load on the beacon nodes. + +To mitigate this additional load, Charon supports configuring a fallback list of beacon nodes. These fallback nodes are only used if all primary beacon nodes fail to respond. This allows operators to designate less critical or public beacon nodes as a backup option, without impacting them under normal conditions. + +To configure fallback beacon nodes, provide a comma-separated list of beacon node URLs using the `--fallback-beacon-node-endpoints` CLI flag. \ No newline at end of file diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/nicknames.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/nicknames.md new file mode 100644 index 0000000000..13f1ab1720 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/nicknames.md @@ -0,0 +1,14 @@ +--- +description: "Add a nickname to your Charon node" +sidebar_label: "Nicknames" +slug: /advanced-and-troubleshooting/advanced/nicknames +unlisted: true +--- + +# Nicknames + +By default, Charon assigns each node a peer name by combining a random adjective with a random name from a predefined list. While these names are human-readable, they are not easily memorable or personalized for operators. + +You can set a personalized nickname for your Charon node by using the `--nickname` CLI flag followed by the desired string. This nickname is shared with other Charon nodes in the same cluster and included as a label in your Prometheus metrics. + +Nicknames can serve various purposes, such as providing a more memorable identifier, including a Discord ID for alerting, or adding a website URL for publicity. \ No newline at end of file diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..568cd2f998 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.5.2 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. +::: diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..f31ebbed63 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,105 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.5.2 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..8c80d667f8 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,38 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency and decentralization, you can opt to host your own relay on a separate open and static internet port. + +```shell +# Figure out your public IP +curl v4.ident.me + +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your public IPv4 or DNS hostname + +nano relay/docker-compose.yml + +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +Note that a local `relay/.charon/charon-enr-private-key` file will be created next to `relay/docker-compose.yml` to ensure a persisted relay ENR across restarts. + +A list of publicly available relays that can be used is maintained [here](../security/risks.md). diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/README.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/README.md new file mode 100644 index 0000000000..08d9fd5147 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Security" +slug: /advanced-and-troubleshooting/security +--- + +# security + diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/bug-bounty.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/bug-bounty.md new file mode 100644 index 0000000000..06a57d0d34 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/bug-bounty.md @@ -0,0 +1,181 @@ +--- +description: "Bug Bounty Policy" +sidebar_label: "Obol Bug Bounty Program" +slug: /advanced-and-troubleshooting/security/bug-bounty +--- + +# Obol Bug Bounty Program + +## Overview + +At Obol Labs, we prioritize the security of our distributed validator software and related services. Our Bug Bounty Program is designed to encourage and reward security researchers for identifying and reporting potential vulnerabilities. This initiative supports our commitment to the security and integrity of our products. + +## Participant Eligibility + +Participants must meet the following criteria to be eligible for the Bug Bounty Program: + +- Not reside in countries where participation in such programs is prohibited. +- Be at least 14 years of age and possess the legal capacity to participate. +- Have received consent from your employer, if applicable. +- Not have been employed or contracted by Obol Labs, nor be an immediate family member of an employee, within the last 12 months. + +## Scope of the Program + +Eligible submissions must involve software and services developed by Obol, specifically under the domains of: + +- Charon the DV Middleware Client +- Obol DV Launchpad and Public API +- Obol Splits Contracts +- Obol Labs hosted Public Relay Infrastructure + +Submissions related to the following are considered out of scope: + +- Social engineering +- Rate Limiting (Non-critical issues) +- Physical security breaches +- Non-security related UX/UI issues +- Third-party application vulnerabilities +- The [Obol](https://obol.org) static website or the Obol infrastructure +- The operational security of node operators running or using Obol software + +## Program Rules + +- Submitted bugs must not have been previously disclosed publicly. +- Only first reports of vulnerabilities will be considered for rewards; previously reported or known vulnerabilities are ineligible. +- The severity of the vulnerability, as assessed by our team, will determine the reward amount. See the "Rewards" section for details. +- Submissions must include a reproducible proof of concept. +- The Obol security team reserves the right to determine the eligibility and reward for each submission. +- Program terms may be updated at Obol's discretion. +- Valid bugs may be disclosed to partner protocols within the Obol ecosystem to enhance overall security. + +## Rewards Structure + +Rewards are issued based on the severity and impact of the disclosed vulnerability, determined at the discretion of Obol Labs. + +### Critical Vulnerabilities: Up to $100,000 + +A Critical-level vulnerability is one that has a severe impact on the security of the in-production system from an unauthenticated external attacker, and requires immediate attention to fix. Highly likely to have a material impact on validator private key security, and/or loss of funds. + +- High impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully exfiltrate BLS (not K1) private key material from a threshold number of operators in the cluster. +- Attacker that is not a member of the cluster can achieve the production of arbitrary BLS signatures from a threshold number of operators in the cluster. +- Attacker can craft a malicious cluster invite capable of subverting even careful review of all data to steal funds during a deposit. +- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield +- Direct loss of funds +- Permanent freezing of funds (fix requires hard fork) +- Network not being able to confirm new transactions (Total network shutdown) +- Protocol insolvency + +### High Vulnerabilities: Up to $10,000 + +For significant security risks that impact the system from a position of low-trust and require a significant effort to fix. + +- High impact, medium likelihood +- Medium impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully partition the cluster and keep the cluster offline indefinitely. +- Attacker that is not a member of the cluster can exfiltrate Charon ENR private keys. +- Attacker that is not a member of the cluster can destroy funds but cannot steal them. +- Unintended chain split (Network partition) +- Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments +- RPC API crash affecting projects with greater than or equal to 25% of the market capitalization on top of the respective layer +- Theft of unclaimed yield +- Theft of unclaimed royalties +- Permanent freezing of unclaimed yield +- Permanent freezing of unclaimed royalties +- Temporary freezing of funds +- Retrieve sensitive data/files from a running server: + - blockchain keys + - database passwords + - (this does not include non-sensitive environment variables, open source code, or usernames) +- Taking state-modifying authenticated actions (with or without blockchain state interaction) on behalf of other users without any interaction by that user, such as: + - Changing cluster information + - Withdrawals + - Making trades + +### Medium Vulnerabilities: Up to $2,500 + +For vulnerabilities with a moderate impact, affecting system availability or integrity. + +- High impact, low likelihood +- Medium impact, medium likelihood +- Low impact, high likelihood + +Impacts: + +- Attacker that is a member of a cluster can exfiltrate K1 key material from another member. +- Attacker that is a member of the cluster can denial of service attack enough peers in the cluster to prevent operation of the validator(s) +- Attacker that is a member of the cluster can bias the protocol in a manner to control the majority of block proposal opportunities. +- Attacker can get a DV Launchpad user to inadvertently interact with a smart contract that is not a part of normal operation of the launchpad. +- Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours +- Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network +- Charon cluster identity private key theft +- Rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle +- Charon public relay node is compromised and leads to cluster topologies getting discovered and disrupted +- Smart contract unable to operate due to lack of token funds +- Block stuffing +- Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol) +- Theft of gas +- Unbounded gas consumption +- Redirecting users to malicious websites (Open Redirect) + +### Low Vulnerabilities: Up to $500 + +For vulnerabilities with minimal impact, unlikely to significantly affect system operations. + +- Low impact, medium likelihood +- Medium impact, low likelihood + +Impacts: + +- Attacker can sometimes put a Charon node in a state that causes it to drop one out of every one hundred attestations made by a validator +- Attacker can display bad data on a non-interactive part of the launchpad. +- Contract fails to deliver promised returns, but doesn't lose value +- Shutdown of greater than 10% or equal to but less than 30% of network processing nodes without brute force actions, but does not shut down the network +- Changing details of other users (including modifying browser local storage) without already-connected wallet interaction and with significant user interaction such as: + - Iframing leading to modifying the backend/browser state (must demonstrate impact with PoC) +- Taking over broken or expired outgoing links such as: + - Social media handles, etc. +- Temporarily disabling user to access target site, such as: + - Locking up the victim from login + - Cookie bombing, etc. + +Rewards may be issued as cash, merchandise, or other forms of recognition, at Obol's discretion. Only one reward will be granted per unique vulnerability. + +## The following activities are prohibited by this bug bounty program + +- Any testing on mainnet or public testnet deployed code; all testing should be done on local-forks of either public testnet or mainnet +- Any testing with pricing oracles or third-party smart contracts +- Attempting phishing or other social engineering attacks against our employees and/or customers +- Any testing with third-party systems and applications (e.g. browser extensions) as well as websites (e.g. SSO providers, advertising networks) +- Any denial of service attacks that are executed against project assets +- Automated testing of services that generate significant amounts of traffic +- Public disclosure of an unpatched vulnerability in an embargoed bounty + +## Submission process + +To report a vulnerability, please contact us at security@obol.tech with: + +- A detailed description of the vulnerability and its potential impact. +- Steps to reproduce the issue. +- Any relevant proof of concept code, screenshots, or documentation. +- Your contact information. + +Incomplete reports may not be eligible for rewards. + +## Disclosure and Confidentiality + +Obol Labs will disclose vulnerabilities and the identity of the researcher (with consent) after remediation. Researchers are required to maintain confidentiality until official disclosure by Obol Labs. + +## Legal and Ethical Compliance + +Participants must adhere to all relevant laws and regulations. Obol Labs will not pursue legal action against researchers reporting vulnerabilities in good faith, but reserves the right to respond to violations of this policy. + +## Non-Disclosure Agreement (NDA) + +Participants may be required to sign an NDA for access to certain proprietary information during their research. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/contact.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/contact.md new file mode 100644 index 0000000000..0b4b54d4fd --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/contact.md @@ -0,0 +1,11 @@ +--- +description: "Security details for the Obol Network" +sidebar_label: "Contacts" +slug: /advanced-and-troubleshooting/security/contact +--- + +# Contacts + +Please email security@obol.tech to report a security incident, vulnerability, bug or inquire about Obol's security. + +Also, visit the [obol security repo](https://github.com/ObolNetwork/obol-security) for more details. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/ev-assessment.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/ev-assessment.md new file mode 100644 index 0000000000..3a666bf1e8 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/ev-assessment.md @@ -0,0 +1,293 @@ +--- +description: "Software Development Security Assessment" +sidebar_label: "Software Development at Obol" +slug: /advanced-and-troubleshooting/security/ev-assessment +--- + +# Software Development at Obol + +When hardening a projects technical security, team member's operational security, and the security of the software development practices in use by the team are some of the most criticial areas to secure. Many hacks and compromises in the space to date have been a result of these attack vectors rather than exploits of the software itself. + +With this in mind, in January 2023 the Obol team retained the expertise of Ethereal Venture's security researcher Alex Wade; to interview key stakeholders and produce a report into the teams Software Development Lifecycle. + +The below page is a result of the report that was produced. What is present here has had some sensitive information redacted, and contains responses to the recommendations made, detailing the actions the Obol team have taken to mitigate what has been highlighted. + +## Obol Report + +**Prepared by: Alex Wade (Ethereal Ventures)** **Date: Jan 2023** + +Over the past month, I worked with Obol to review their software development practices in preparation for their upcoming security audits. My goals were to review and analyze: + +* Software development processes +* Vulnerability disclosure and escalation procedures +* Key personnel risk + +The information in this report was collected through a series of interviews with Obol’s project leads. + +## Contents + +* Background Info +* Analysis - Cluster Setup and DKG + * Key Risks + * Potential Attack Scenarios +* Recommendations + * R1: Users should deploy cluster contracts through a known on-chain entry point + * R2: Users should deposit to the beacon chain through a pool contract + * R3: Raise the barrier to entry to push an update to the Launchpad +* Additional Notes + * Vulnerability Disclosure + * Key Personnel Risk + +## Background Info + +**Each team lead was asked to describe Obol in terms of its goals, objectives, and key features.** + +### What is Obol? + +Obol builds DVT (Distributed Validator Technology) for Ethereum. + +### What is Obol’s goal? + +Obol’s goal is to solve a classic distributed systems problem: uptime. + +Rather than requiring Ethereum validators to stake on their own, Obol allows groups of operators to stake together. Using Obol, a single validator can be run cooperatively by multiple people across multiple machines. + +In theory, this architecture provides validators with some redundancy against common issues: server and power outages, client failures, and more. + +### What are Obol’s objectives? + +Obol’s business objective is to provide base-layer infrastructure to support a distributed validator ecosystem. As Obol provides base layer technology, other companies and projects will build on top of Obol. + +Obol’s business model is to eventually capture a portion of the revenue generated by validators that use Obol infrastructure. + +### What is Obol’s product? + +Obol’s product consists of three main components, each run by its own team: a webapp, a client, and smart contracts. + +* [DV Launchpad](../../learn/intro/launchpad.md): A webapp to create and manage distributed validators. +* [Charon](../../learn/charon/intro.md): A middleware client that enables operators to run distributed validators. +* [Solidity](../../learn/intro/obol-splits.md): Withdrawal and fee recipient contracts for use with distributed validators. + +## Analysis - Cluster Setup and DKG + +The Launchpad guides users through the process of creating a cluster, which defines important parameters like the validator’s fee recipient and withdrawal addresses, as well as the identities of the operators in the cluster. In order to ensure their cluster configuration is correct, users need to rely on a few different factors. + +**First, users need to trust the Charon client** to perform the DKG correctly, and validate things like: + +* Config file is well-formed and is using the expected version +* Signatures and ENRs from other operators are valid +* Cluster config hash is correct +* DKG succeeds in producing valid signatures +* Deposit data is well-formed and is correctly generated from the cluster config and DKG. + +However, Charon’s validation is limited to the digital: signature checks, cluster file syntax, etc. It does NOT help would-be operators determine whether the other operators listed in their cluster definition are the real people with whom they intend to start a DVT cluster. So - + +**Second, users need to come to social consensus with fellow operators.** While the cluster is being set up, it’s important that each operator is an active participant. Each member of the group must validate and confirm that: + +* the cluster file correctly reflects their address and node identity, and reflects the information they received from fellow operators +* the cluster parameters are expected – namely, the number of validators and signing threshold + +**Finally, users need to perform independent validation.** Each user should perform their own validation of the cluster definition: + +* Is my information correct? (address and ENR) +* Does the information I received from the group match the cluster definition? +* Is the ETH2 deposit data correct, and does it match the information in the cluster definition? +* Are the withdrawal and fee recipient addresses correct? + +These final steps are potentially the most difficult, and may require significant technical knowledge. + +## Key Risks + +### 1. Validation of Contract Deployment and Deposit Data Relies Heavily on Launchpad + +From my interviews, it seems that the user deploys both the withdrawal and fee recipient contracts through the Launchpad. + +What I’m picturing is that during the first parts of the cluster setup process, the user is prompted to sign one or more transactions deploying the withdrawal and fee recipient contracts to mainnet. The Launchpad apparently uses an npm package to deploy these contracts: `0xsplits/splits-sdk`, which I assume provides either JSON artifacts or a factory address on chain. The Launchpad then places the deployed contracts into the cluster config file, and the process moves on. + +If an attacker has published a malicious update to the Launchpad (or compromised an underlying dependency), the contracts deployed by the Launchpad may be malicious. The questions I’d like to pose are: + +* How does the group creator know the Launchpad deployed the correct contracts? +* How does the rest of the group know the creator deployed the contracts through the Launchpad? + +My understanding is that this ultimately comes down to the independent verification that each of the group’s members performs during and after the cluster’s setup phase. + +At its worst, this verification might consist solely of the cluster creator confirming to the others that, yes, those addresses match the contracts I deployed through the Launchpad. + +A more sophisticated user might verify that not only do the addresses match, but the deployed source code looks roughly correct. However, this step is far out of the realm of many would-be validators. To be really certain that the source code is correct would require auditor-level knowledge. + +The risk is that: + +* the deployed contracts are NOT the correctly-configured 0xsplits waterfall/fee splitter contracts +* most users are ill-equipped to make this determination themselves +* we don’t want to trust the Launchpad as the single source of truth + +In the worst case, the cluster may end up depositing with malicious withdrawal or fee recipient credentials. If unnoticed, this may net an attacker the entire withdrawal amount, once the cluster exits. + +Note that the same (or similar) risks apply to validation of deposit data, which has the potential to be similarly difficult. I’m a little fuzzy on which part of the Obol stack actually generates the deposit data / deposit transaction, so I can’t speak to this as much. However, I think the mitigation for both of these is roughly the same - read on! + +**Mitigation:** + +It’s certainly a good idea to make it harder to deploy malicious updates to the Launchpad, but this may not be entirely possible. A higher-yield strategy may be to educate and empower users to perform independent validation of the DVT setup process - without relying on information fed to them by Charon and the Launchpad. + +I’ve outlined some ideas for this in #R1 and #R2. + +### 2. Social Consensus, aka “Who sends the 32 ETH?” + +Depositing to the beacon chain requires a total of 32 ETH. Obol’s product allows multiple operators to act as a single validator together, which means would-be operators need to agree on how to fund the 32 ETH needed to initiate the deposit. + +It is my understanding that currently, this process comes down to trust and loose social consensus. Essentially, the group needs to decide who chips in what amount together, and then trust someone to take the 32 ETH and complete the deposit process correctly (without running away with the money). + +Granted, the initial launch of Obol will be open only to a small group of people as the kinks in the system get worked out - but in preparation for an eventual public release, the deposit process needs to be much simpler and far less reliant on trust. + +Mitigation: See #R2. + +**Potential Attack Scenarios** + +During the interview process, I learned that each of Obol’s core components has its own GitHub repo, and that each repo has roughly the same structure in terms of organization and security policies. For each repository: + +* There are two overall github organization administrators, and a number of people have administrative control over individual repositories. +* In order to merge PRs, the submitter needs: + * CI/CD checks to pass + * Review from one person (anyone at Obol) + +Of course, admin access also means the ability to change these settings - so repo admins could theoretically merge PRs without needing checks to pass, and without review/approval, organization admins can control the full GitHub organization. + +The following scenarios describe the impact an attack may have. + +**1. Publishing a malicious version of the Launchpad, or compromising an underlying dependency** + +* Reward: High +* Difficulty: Medium-Low + +As described in Key Risks, publishing a malicious version of the Launchpad has the potential to net the largest payout for an attacker. By tampering with the cluster’s deposit data or withdrawal/fee recipient contracts, an attacker stands to gain 32 ETH or more per compromised cluster. + +During the interviews, I learned that merging PRs to main in the Launchpad repo triggers an action that publishes to the site. Given that merges can be performed by an authorized Obol developer, this makes the developers prime targets for social engineering attacks. + +Additionally, the use of the `0xsplits/splits-sdk` NPM package to aid in contract deployment may represent a supply chain attack vector. It may be that this applies to other Launchpad dependencies as well. + +In any case, with a fairly large surface area and high potential reward, this scenario represents a credible risk to users during the cluster setup and DKG process. + +See #R1, #R2, and #R3 for some ideas to address this scenario. + +**2. Publishing a malicious version of Charon to new operators** + +* Reward: Medium +* Difficulty: High + +During the cluster setup process, Charon is responsible both for validating the cluster configuration produced by the Launchpad, as well as performing a DKG ceremony between a group’s operators. + +If new operators use a malicious version of Charon to perform this process, it may be possible to tamper with both of these responsibilities, or even get access to part or all of the underlying validator private key created during DKG. + +However, the difficulty of this type of attack seems quite high. An attacker would first need to carry out the same type of social engineering attack described in scenario 1 to publish and tag a new version of Charon. Crucially, users would also need to install the malicious version - unlike the Launchpad, an update here is not pushed directly to users. + +As long as Obol is clear and consistent with communication around releases and versioning, it seems unlikely that a user would both install a brand-new, unannounced release, and finish the cluster setup process before being warned about the attack. + +**3. Publishing a malicious version of Charon to existing validators** + +* Reward: Low +* Difficulty: High + +Once a distributed validator is up and running, much of the danger has passed. As a middleware client, Charon sits between a validator’s consensus and validator clients. As such, it shouldn’t have direct access to a validator’s withdrawal keys nor signing keys. + +If existing validators update to a malicious version of Charon, it’s likely the worst thing an attacker could theoretically do is slash the validator, however, assuming Charon has no access to any private keys, this would be predicated on one or more validator clients connected to Charon also failing to prevent the signing of a slashable message. In practice, a compromised Charon client is more likely to pose liveness risks than safety risks. + +This is not likely to be particularly motivating to potential attackers - and paired with the high difficulty described above, this scenario seems unlikely to cause significant issues. + +## Recommendations + +### R1: Users should deploy cluster contracts through a known on-chain entry point + +During setup, users should only sign one transaction via the Launchpad - to a contract located at an Obol-held ENS (e.g. `launchpad.obol.eth`). This contract should deploy everything needed for the cluster to operate, like the withdrawal and fee recipient contracts. It should also initialize them with the provided reward split configuration (and any other config needed). + +Rather than using an NPM library to supply a factory address or JSON artifacts, this has the benefit of being both: + +* **Harder to compromise:** as long as the user knows launchpad.obol.eth, it’s pretty difficult to trick them into deploying the wrong contracts. +* **Easier to validate** for non-technical users: the Obol contract can be queried for deployment information via etherscan. For example:\ + ![](/img/gitbook/image-50.png) + +Note that in order for this to be successful, Obol needs to provide detailed steps for users to perform manual validation of their cluster setups. Users should be able to treat this as a “checklist:” + +* Did I send a transaction to `launchpad.obol.eth`? +* Can I use the ENS name to locate and query the deployment manager contract on etherscan? +* If I input my address, does etherscan report the configuration I was expecting? + * withdrawal address matches + * fee recipient address matches + * reward split configuration matches + +As long as these steps are plastered all over the place (i.e. not just on the Launchpad) and Obol puts in effort to educate users about the process, this approach should allow users to validate cluster configurations themselves - regardless of Launchpad or NPM package compromise. + +**Obol’s response** + +Roadmapped: add the ability for the OWR factory to claim and transfer its reverse resolution ownership. + +### R2: Users should deposit to the beacon chain through a pool contract + +Once cluster setup and DKG is complete, a group of operators should deposit to the beacon chain by way of a pool contract. The pool contract should: + +* Accept Eth from any of the group’s operators +* Stop accepting Eth when the contract’s balance hits (32 ETH \* number of validators) +* Make it easy to pull the trigger and deposit to the beacon chain once the critical balance has been reached +* Offer all of the group’s operators a “bail” option at any point before the deposit is triggered + +Ideally, this contract is deployed during the setup process described in #R1, as another step toward allowing users to perform independent validation of the process. + +Rather than relying on social consensus, this should: + +* Allow operators to fund the validator without needing to trust any single party +* Make it harder to mess up the deposit or send funds to some malicious actor, as the pool contract should know what the beacon deposit contract address is + +**Obol’s response** + +Roadmapped: give the operators a streamlined, secure way to deposit Ether (ETH) to the beacon chain collectively, satisfying specific conditions: + +* Pooling from multiple operators. +* Ceasing to accept ETH once a critical balance is reached, defined by 32 ETH multiplied by the number of validators. +* Facilitating an immediate deposit to the beacon chain once the target balance is reached. +* Provide a 'bail-out' option for operators to withdraw their contribution before initiating the group's deposit to the beacon chain. + +### R3: Raise the barrier to entry to push an update to the Launchpad + +Currently, any repo admin can publish an update to the Launchpad unchecked. + +Given the risks and scenarios outlined above, consider amending this process so that the sole compromise of either admin is not sufficient to publish to the Launchpad site. It may be worthwhile to require both admins to approve publishing to the site. + +Along with simply adding additional prerequisites to publish an update to the Launchpad, ensure that both admins have enabled some level of multi-factor authentication on their GitHub accounts. + +**Obol’s response** + +We removed individual’s ability to merge changes without review, enforced MFA, signed commits, and employed Bulldozer bot to make sure a PR gets merged automatically when all checks pass. + +## Additional Notes + +### Vulnerability Disclosure + +During the interviews, I got some conflicting information when asking about Obol’s vulnerability disclosure process. + +Some interviewees directed me towards Obol’s security repo, which details security contacts: [ObolNetwork/obol-security](https://github.com/ObolNetwork/obol-security), while some answered that disclosure should happen primarily through Immunefi. While these may both be part of the correct answer, it seems that Obol’s disclosure process may not be as well-defined as it could be. Here are some notes: + +* I wasn’t able to find information about Obol on Immunefi. I also didn’t find any reference to a security contact or disclosure policy in Obol’s docs. +* When looking into the obol security repo, I noticed broken links in a few of the sections in README.md and SECURITY.md: + * Security policy + * More Information +* Some of the text and links in the Bug Bounty Program don’t seem to apply to Obol (see text referring to Vaults and Strategies). +* The Receiving Disclosures section does not include a public key with which submitters can encrypt vulnerability information. + +It’s my understanding that these items are probably lower priority due to Obol’s initial closed launch - but these should be squared away soon! \[Obol response to latest vuln disclosure process goes here] + +**Obol’s response** + +we addressed all of the concerns in the obol-security repository: + +1. The security policy link has been fixed +2. The Bug Bounty program received an overhaul and clearly states rewards, eligibility, and scope +3. We list two GPG public keys for which we accept encrypted vulnerabilities reports. + +We are actively working towards integrating Immunefi in our security pipeline. + +### Key Personnel Risk + +A final section on the specifics of key personnel risk faced by Obol has been redacted from the original report. Particular areas of control highlighted were github org ownership and domain name control. + +**Obol’s response** + +These risks have been mitigated by adding an extra admin to the github org, and by setting up a second DNS stack in case the primary one fails, along with general Opsec improvements. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/overview.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/overview.md new file mode 100644 index 0000000000..d56083987f --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/overview.md @@ -0,0 +1,38 @@ +--- +description: "Security Overview" +sidebar_label: "Overview" +slug: /advanced-and-troubleshooting/security/overview +--- + +# Overview + +This page serves as an overview of the Obol Network from a security point of view. + +This page is updated quarterly. The last update was on 2024-June-19. + +## Table of Contents + +* [Overview](overview.md) + * [Table of Contents](overview.md#table-of-contents) + * [List of Security Audits and Assessments](overview.md#list-of-security-audits-and-assessments) + * [Security focused documents](overview.md#security-focused-documents) + * [Bug Bounty](overview.md#bug-bounty) + +## List of Security Audits and Assessments + +The completed audits reports are linked [here](https://github.com/ObolNetwork/obol-security/tree/main/audits). + +* A review of Obol Labs [development processes](./ev-assessment.md) by [Ethereal Ventures](https://www.etherealventures.com/). +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/) resulting in version [`v0.16.0`](https://github.com/ObolNetwork/charon/releases/tag/v0.16.0). +* A second [assessment of Charon](https://obol.tech/charon_quantstamp_assessment.pdf) by [QuantStamp](https://quantstamp.com/) resulting in version [`v0.19.1`](https://github.com/ObolNetwork/charon/releases/tag/v0.19.1). +* A [solidity audit](./smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* A [penetration testing certificate](https://github.com/ObolNetwork/obol-security/blob/main/audits/Sayfer_2024-03_Penetration_Testing_CFD.pdf) of the Obol DV Launchpad by [Sayfer](https://sayfer.io/). +* A second [solidity audit](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V2%20Audit%20-%20Nethermind.pdf) by [Nethermind](https://nethermind.io). + +## Security focused documents + +* A [threat model](./threat_model.md) for a DV middleware client like Charon. + +## Bug Bounty + +Information related to disclosing bugs and vulnerabilities to Obol can be found on [the next page](bug-bounty.md). diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/risks.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/risks.md new file mode 100644 index 0000000000..46d2302a3d --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/risks.md @@ -0,0 +1,53 @@ +--- +description: "Outlining potential centralization risks and their mitigations" +sidebar_label: "Centralization Risks and Mitigation" +slug: /advanced-and-troubleshooting/security/risks +--- + +# Centralization Risks and Mitigation + +## Risk: Obol hosting the relay infrastructure + +**Mitigation**: Self-host a relay. + +One of the risks associated with Obol hosting the [LibP2P relays](../../learn/charon/charon-networking.md) infrastructure allowing peer discovery is that if Obol-hosted relays go down, peers won't be able to discover each other and perform the DKG. To mitigate this risk, external organizations and node operators can consider self-hosting a relay. This way, if Obol's relays go down, the clusters can still operate through other relays in the network. Ensure that all nodes in the cluster use the same relays, or they will not be able to find each other if they are connected to different relays. + +The following non-Obol entities run relays that you can consider adding to your cluster (you can have more than one per cluster, see the `--p2p-relays` flag of [`charon run`](../../learn/charon/charon-cli-reference.md#the-run-command)): + +| Entity | Relay URL | +| ------------------------------------------- | ------------------------------------ | +| [DSRV](https://www.dsrvlabs.com/) | https://charon-relay.dsrvlabs.dev | +| [Infstones](https://infstones.com/) | https://obol-relay.infstones.com/ | +| [Hashquark](https://www.hashquark.io/) | https://relay-2.prod-relay.721.land/ | +| [Figment](https://figment.io/) | https://relay-1.obol.figment.io/ | +| [Node Guardians](https://nodeguardians.io/) | https://obol-relay.nodeguardians.io/ | + +## Risk: Obol being able to update Charon code + +**Mitigation**: Pin specific docker versions or compile from source on a trusted commit. + +Another risk associated with Obol is the Labs team having the ability to update the [Charon code](https://github.com/ObolNetwork/charon) used by node operators within DV clusters, which could introduce vulnerabilities or malicious code. To mitigate this risk, operators can consider pinning specific versions or hashes of the Docker image or git repo commits that have been [thoroughly tested](overview.md#list-of-security-audits-and-assessments) and accepted by the network. This would ensure that any updates are carefully vetted and reviewed by the community, and only introduced into a running cluster gradually. The labs team will strive to communicate the security or operational impact any Charon update entails, giving operators the chance to decide whether they want potential performance or quality of experience improvements, or whether they remain on a trusted version for longer. + +## Risk: Obol hosting the DV Launchpad + +**Mitigation**: Use [`create cluster`](../../learn/charon/charon-cli-reference.md#the-create-command) or [`create dkg`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) locally and distribute the files manually. + +Hosting the first Charon frontend, the [DV Launchpad](../../learn/intro/launchpad.md), on a centralized server could create a single point of failure, as users would have to rely on Obol's server to access the protocol. This could limit the decentralization of the protocol and could make it vulnerable to attacks or downtime. Obol hosting the launchpad on a decentralized network, such as IPFS would be a first step but not enough. This is why the Charon code is source-available and contains a CLI interface to interact with the protocol locally. + +To mitigate the risk of launchpad failure, consider using the `create cluster` or `create dkg` commands locally and distributing the key shares files manually. + +## Risk: Obol custodying pre-signed exit messages + +**Mitigation**: Use withdrawal address initiated exits or validator client exits + +Before the Pectra hardfork, there was no way for a delegator to exit their validator without the co-operation of the node operator(s). In an effort to reduce this risk, Obol developed the [Charon exit](../../learn/charon/charon-cli-reference.md#the-exit-command) command, which allows operators to pre-sign and download exit messages to give to the delegator for safe keeping, ensuring they could broadcast them at any point in time. This feature relies on Obol's [API](../../api/what-is-this-api), and means the Obol core team could in theory initiate an unwanted exit. If a delegator does not want to be exposed to that centralization risk, they should not use Charon's built-in exit commands, and instead should initiate exits using the [EIP7002](https://eips.ethereum.org/EIPS/eip-7002) exit contract, or alternatively by running normal exit commands on the operator's validator clients. + +Guides to exiting validators using all three approaches are outlined [here](../../run-a-dv/running/exit-a-dv.mdx). + +## Risk: Obol going bust/rogue + +**Mitigation**: Use key recovery. + +The final centralization risk associated with Obol is the possibility of the company going bankrupt or acting maliciously, which could lead to a loss of confidence in the Charon client. To mitigate this risk, Obol has implemented a key reconstitution mechanism. This would allow the clusters to continue operating and to (re)create full validator private keys suitable for standard staking setups even if Obol is no longer able or willing to provide support. + +A guide to recombine key shares into a single private key can be accessed [here](../advanced/quickstart-combine.md). diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/smart-contract-audit.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/smart-contract-audit.md new file mode 100644 index 0000000000..c23023dd88 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/smart-contract-audit.md @@ -0,0 +1,467 @@ +--- +sidebar_label: "Smart Contract Audit" +slug: /advanced-and-troubleshooting/security/smart-contract-audit +--- + +# Smart Contract Audit + +## Obol Audit Report: Obol Manager Contracts + +Prepared by: Zach Obront, Independent Security Researcher + +Date: Sept 18 to 22, 2023 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2023%20-%20Obol%20Splits%20V1%20Audit%20-%20Zach%20Obront.pdf) + +### About **Obol**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-obol) {#about-obol} +The Obol Network is an ecosystem for trust minimized staking that enables people to create, test, run & co-ordinate distributed validators. + +The Obol Manager contracts are responsible for distributing validator rewards and withdrawals among the validator and node operators involved in a distributed validator. + +### About **zachobront**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-zachobront) {#about-zachobront} +Zach Obront is an independent smart contract security researcher. He serves as a Lead Senior Watson at Sherlock, a Security Researcher at Spearbit, and has identified multiple critical severity bugs in the wild, including in a Top 5 Protocol on Immunefi. You can say hi on Twitter at [@zachobront](http://twitter.com/zachobront). + +### Summary & Scope[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary--scope) {#summary--scope} +The [ObolNetwork/obol-manager-contracts](https://github.com/ObolNetwork/obol-manager-contracts/) repository was audited at commit [50ce277919723c80b96f6353fa8d1f8facda6e0e](https://github.com/ObolNetwork/obol-manager-contracts/tree/50ce277919723c80b96f6353fa8d1f8facda6e0e). + +The following contracts were in scope: + +* src/controllers/ImmutableSplitController.sol +* src/controllers/ImmutableSplitControllerFactory.sol +* src/lido/LidoSplit.sol +* src/lido/LidoSplitFactory.sol +* src/owr/OptimisticWithdrawalReceiver.sol +* src/owr/OptimisticWithdrawalReceiverFactory.sol + +After completion of the fixes, the [2f4f059bfd145f5f05d794948c918d65d222c3a9](https://github.com/ObolNetwork/obol-manager-contracts/tree/2f4f059bfd145f5f05d794948c918d65d222c3a9) commit was reviewed. After this review, the updated Lido fee share system in [PR #96](https://github.com/ObolNetwork/obol-manager-contracts/pull/96/files) (at commit [fd244a05f964617707b0a40ebb11b523bbd683b8](https://github.com/ObolNetwork/obol-splits/pull/96/commits/fd244a05f964617707b0a40ebb11b523bbd683b8)) was reviewed. + +### Summary of Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary-of-findings) {#summary-of-findings} +| Identifier | Title | Severity | Fixed | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------- | ----- | +| [M-01](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) | Future fees may be skirted by setting a non-ETH reward token | Medium | ✓ | +| [M-02](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) | Splits with 256 or more node operators will not be able to switch on fees | Medium | ✓ | +| [M-03](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) | In a mass slashing event, node operators are incentivized to get slashed | Medium | | +| [L-01](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) | Obol fees will be applied retroactively to all non-distributed funds in the Splitter | Low | ✓ | +| [L-02](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) | If OWR is used with rebase tokens and there's a negative rebase, principal can be lost | Low | ✓ | +| [L-03](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) | LidoSplit can receive ETH, which will be locked in contract | Low | ✓ | +| [L-04](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) | Upgrade to latest version of Solady to fix LibClone bug | Low | ✓ | +| [G-01](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) | stETH and wstETH addresses can be saved on implementation to save gas | Gas | ✓ | +| [G-02](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) | OWR can be simplified and save gas by not tracking distributedFunds | Gas | ✓ | +| [I-01](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) | Strong trust assumptions between validators and node operators | Informational | | +| [I-02](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) | Provide node operator checklist to validate setup | Informational | | + +### Detailed Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#detailed-findings) {#detailed-findings} +#### \[M-01] Future fees may be skirted by setting a non-ETH reward token[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) {#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token} +Fees are planned to be implemented on the `rewardRecipient` splitter by updating to a new fee structure using the `ImmutableSplitController`. + +It is assumed that all rewards will flow through the splitter, because (a) all distributed rewards less than 16 ETH are sent to the `rewardRecipient`, and (b) even if a team waited for rewards to be greater than 16 ETH, rewards sent to the `principalRecipient` are capped at the `amountOfPrincipalStake`. + +This creates a fairly strong guarantee that reward funds will flow to the `rewardRecipient`. Even if a user were to set their `amountOfPrincipalStake` high enough that the `principalRecipient` could receive unlimited funds, the Obol team could call `distributeFunds()` when the balance got near 16 ETH to ensure fees were paid. + +However, if the user selects a non-ETH token, all ETH will be withdrawable only thorugh the `recoverFunds()` function. If they set up a split with their node operators as their `recoveryAddress`, all funds will be withdrawable via `recoverFunds()` without ever touching the `rewardRecipient` or paying a fee. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation) + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept) + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-1) + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-1) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendations) + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-2) + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-2) + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-3) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-3) + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-4) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-1) + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-4) + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-5) + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-2) + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-5) + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-6) + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-6) + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-7) + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-7) + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-8) + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-9) + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-10) + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\ diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..932cec0f71 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,155 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritize the liveliness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalize operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator. A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..1ed84c4d89 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# troubleshooting + diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..f8ffd3566c --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,298 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting anything other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +For now, ENR rotation/replacement is not supported, it will be supported in a future release. Therefore, its advised to always keep a backup of your `charon-enr-private-key ` in a secure location (ex: cloud storage, USB Flash drive, etc.). + +### I can't find the keys anywhere +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows. +Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + + +## Lighthouse + + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + + +### Lighthouse gives the error `not enough time for a discovery seach` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance. +Using 3rd party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Can't connect to Beacon API` + +If you are running EL and CL outside Obol on the same machine, you might need to open ports in your firewall to allow connections incoming from the docker instance. +In order to know the IP of the docker network, run: +`docker network inspect ` + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is +probably not online to sign successfully. Make sure all operators are +running the latest version of Charon. To check if some peers are not online: +`docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key +should be created and placed in the right directory during the ceremony. +Also, make sure you are working in the right directory: +`charon-distributed-validator-node`. + +### `Failed to confirm node connection` +Wait for Teku & Lighthouse sync to be complete. + + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum +limit has been reached. This is most often due to "maximum reservations per IP/peer". +This is when your Charon node is restarting or in some error loop and constantly +attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it. +This should allow the relay enough time to reset your IP/peer limits and +should then allow new reservations. This could also be due to the relay +being overloaded in general, so reaching a server wide "maximum connections" +limit. This is an issue with relay scalability and we are working in a long +term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO_RESERVATION (204)` indicates the peer +isn't connected to the relay, so the the Charon client cannot connect to the +peer via the relay. That might be because the peer is offline or the peer is +configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact +same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when +it failed to fetch the required data from the beacon node API. This indicates +a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +attestation data. This indicates the associated attestation duty failed to obtain +a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed due to no partial v2 committee subscription submitted by the cluster +validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to insufficient +partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to no partial randao +signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This +could indicate that insufficient honest peers participated in consensus or p2p +network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted +by the local validator client. This could indicate that the local validator client +is offline, or has connection problems with Charon, or has some other problem. +See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database +as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was +received from any peer. This indicates all peers are offline or p2p network connection +problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures +for the duty was received from peers. This indicates problems with peers or p2p +network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient +partial signatures failed. This indicates inconsistent signed data. This indicates +a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it +checks for a special file called the private key lock file. This file has the +same name as the ENR private key file but with a `.lock` extension. +If the private key lock file exists and is not older than 5 seconds, Charon won't +run. It doesn't allow running multiple Charon instances with the same ENR private +key. If the private key lock file has a timestamp older than 5 seconds, Charon +will replace it and continue with its work. If you`re sure that no other Charon +instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the +validators private key shares don't match the ENR private key. There may +have been a mix-up during deployment, leading to a mismatching validator +client key share index. + +For example:Imagine node N is Alice, and node M is Bob, the error would read: +` mismatching validator client key share index, Bob`s key share submitted to Alice`s charon node ` +Bob`s private key share(s) are imported to a VC that is connected to +Alice`s Charon node. This is a invalid setup/deployment. +Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside +cluster-lock.json and see that matches with the public key inside +`node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data first time around. +You can solve this by following the steps below: +- Click the Wheel Icon > Datasources. +- Click prometheus. +- Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +- Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel +Can be linked to a Teku keystore issue. + + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + You can ignore this error unless you have been contacted by the Obol Team + with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. + + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly +on Linux and WSL for Windows systems. In the interest of security, the +charon docker image runs as a non-root user, and this user often does not +have the permissions to write in the directory you have checked out the code +to. This can be generally be fixed with some of the following: +- Running docker commands with `sudo`, if you haven't [setup docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +- Changing the permissions of the `.charon` folder with the commands: + - `mkdir .charon` (if it doesn't already exist); + - `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + It`s because both Nethermind and Lighthouse start syncing and so there's + connectivity issues among the containers. Simply let the containers run for + a while. You won't observe frequent errors when Nethermind finishes syncing. You + can also add a second beacon node endpoint for something like Infura by + adding a comma separated API URL to the end of + `CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. + +### How do I fix the `plugin "loki" not found` error? + If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + + +## Relay + +### ` Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the +relay/docker-compose.yml with your real public IP or DNS hostname. + +### ` Timeout resolving bootnode ENR: context deadline exceeded` +The relay you are trying to connect to your peers via is offline or +unreachable. + diff --git a/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..d10b59653d --- /dev/null +++ b/versioned_docs/version-v1.5/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or un-conctactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.5/api/address.mdx b/versioned_docs/version-v1.5/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.5/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.5/api/cluster-definition.mdx b/versioned_docs/version-v1.5/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.5/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.5/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.5/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..4da8ad1bcc --- /dev/null +++ b/versioned_docs/version-v1.5/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Effectiveness + + diff --git a/versioned_docs/version-v1.5/api/cluster-lock.mdx b/versioned_docs/version-v1.5/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.5/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.5/api/dv-exit.mdx b/versioned_docs/version-v1.5/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.5/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.5/api/metrics.mdx b/versioned_docs/version-v1.5/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.5/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.5/api/owr-information.mdx b/versioned_docs/version-v1.5/api/owr-information.mdx new file mode 100644 index 0000000000..0e20b4892a --- /dev/null +++ b/versioned_docs/version-v1.5/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR + + diff --git a/versioned_docs/version-v1.5/api/state.mdx b/versioned_docs/version-v1.5/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.5/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.5/api/system.mdx b/versioned_docs/version-v1.5/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.5/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.5/api/techne-credentials.mdx b/versioned_docs/version-v1.5/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.5/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.5/api/terms-and-conditions.mdx b/versioned_docs/version-v1.5/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..d5d32a5dba --- /dev/null +++ b/versioned_docs/version-v1.5/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TermsAndConditions + + + + diff --git a/versioned_docs/version-v1.5/api/what-is-this-api.md b/versioned_docs/version-v1.5/api/what-is-this-api.md new file mode 100644 index 0000000000..6951dbffbb --- /dev/null +++ b/versioned_docs/version-v1.5/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://launchpad.obol.org), a dApp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API can also be used via the [Obol-SDK](../sdk/index.md). + +Read more about Obol and how to use the [launchpad](https://launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.5/community-and-governance/community/README.md b/versioned_docs/version-v1.5/community-and-governance/community/README.md new file mode 100644 index 0000000000..c8d5f1c1b9 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# community + diff --git a/versioned_docs/version-v1.5/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.5/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..6c09edfaa7 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/community/staking-masters.md @@ -0,0 +1,28 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\ + + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.5/community-and-governance/community/techne.md b/versioned_docs/version-v1.5/community-and-governance/community/techne.md new file mode 100644 index 0000000000..55b5a75905 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/community/techne.md @@ -0,0 +1,119 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\ + + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::info For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. ::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.gg/obolnetwork) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.gg/obol) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.gg/obol) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.5/community-and-governance/contribution/README.md b/versioned_docs/version-v1.5/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..5cff17667a --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# contribution + diff --git a/versioned_docs/version-v1.5/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.5/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +````markdown + ```javascript + console.log(error); + ``` +```` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.5/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.5/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e17d6226af --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +- Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +- Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/README.md b/versioned_docs/version-v1.5/community-and-governance/governance/README.md new file mode 100644 index 0000000000..4dca7a7d08 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/README.md @@ -0,0 +1,57 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# Governance + +The Obol Collective is building a decentralized governance system rooted in the core values of Web3: transparency, openness, collaboration, and community-led decision making. At the same time, we recognize that decentralization is a journey, not a switch. Our aim is to progressively decentralize Obol governance in a way that is sustainable, resilient, and free of the common pitfalls that have emerged in the ecosystem. + +## Our Vision: Pragmatic Decentralization + +We are here to stay. And we believe the only way to build a resilient and successful decentralized collective is to start by building a strong foundation. In recent months, many leading DAOs have experienced operational bottlenecks, inefficiency, and growing pains from decentralizing too fast, too early. The result? Several are now walking back toward more centralized structures to regain coordination capacity, accountability, and operational agility. + +We’ve learned from these examples. Our approach is different: we are deliberately not rushing into maximal decentralization. Instead, we are laying the groundwork for progressive, sustainable decentralization over time. + +At this stage of the Collective, execution matters. Proposals are already going through governance processes, but the Obol Association still holds executional authority to move quickly where needed. We see this as a temporary and necessary condition to keep building and shipping. This balance, transparent governance with accountable execution, is critical to avoid decision paralysis. + +Governance at Obol is not about decentralization for its own sake. It is about enabling the best decisions for the long-term health of the network. As emphasized in the [Bell Curve governance roundtable](https://youtu.be/vF8XuRuZs9g?si=0dw3uh8gLXyvFlUH), decentralization without shared purpose or coordination leads to deadlock. We aim to build a governance model that supports rather than hinders progress. + +## Inspiration + +We draw inspiration from both the successes and challenges of other DAOs. In particular: + +* [**Arbitrum DAO**](https://forum.arbitrum.foundation/t/a-vision-for-the-future-of-arbitrum/28962), Introduced “Arbitrum Aligned Entities” to fix governance gridlock by assigning execution to focused teams, while keeping strategic control with the DAO. A response to over-decentralizing too quickly and losing operational clarity. +* [**Compound**](https://www.comp.xyz/t/proposal-to-create-the-compound-foundation/6777?utm_source=substack\&utm_medium=email), Proposed the Compound Foundation to help the DAO coordinate services, manage treasury execution, and maintain continuity — moving from pure DAO toward a hybrid model with accountable support. + +These initiatives reinforce our belief that progressive decentralization, aligned with clear domain ownership and accountable entities, leads to more sustainable governance. + +## Principles We Follow + +* **Decentralization is a means, not an end.** Governance exists to serve the network, not to complicate it. +* **Stakeholders should govern what they understand.** Validators and technical contributors guide protocol upgrades; token holders lead incentive and treasury decisions. +* **Social consensus is paramount.** On-chain votes matter, but upgrades only succeed through real-world coordination and adoption. +* **Structures must evolve with the protocol.** Governance at genesis won’t look like governance at maturity. We are building toward that future in deliberate steps. + +## Governance Tools + +To support transparent decision-making and empower active participation, here are key tools used across the Collective: + +* [**Governance Forum**](https://community.obol.org/) – for proposal discussion and coordination +* [**Voting Portal**](https://vote.obol.org/) – to delegate or vote on proposals +* [**Dune Dashboard**](https://dune.com/vistawtf/obol-governance) – to track voting data and delegate participation +* [**Staking Portal**](https://stake.obol.org/) – to stake OBOL and receive stOBOL +* [**0xretro.xyz**](https://0xretro.xyz/) – to access key info and metrics about delegates + +## Governance Sections + +The Obol governance documentation is organized into the following sections: + +* [collective.md](collective.md "mention") – framing the governance bodies, roles, and progressive decentralization pathway +* [token-house.md](token-house.md "mention") – the token-holder-based decision-making layer of the Collective +* [raf](raf/README.md "mention") – information for delegates participating in the Retroactive Funding Program (RAF) +* [grants-program](grants-program/README.md "mention") – the Obol funding mechanism for contributors and ecosystem support, led by the Obol Association + +_These sections evolve as the governance process matures. For any feedback, ideas, or questions, we invite you to join the discussion on the_ [_Forum_](https://community.obol.org/) _or reach out via_ [_Discord_](https://discord.gg/obol)_._ + +**Together, we are building governance for the long term.** diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/collective.md b/versioned_docs/version-v1.5/community-and-governance/governance/collective.md new file mode 100644 index 0000000000..4b93a757a8 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/collective.md @@ -0,0 +1,62 @@ +--- +description: "Obol Collective Overview" +sidebar_label: "Collective Overview" +slug: /community-and-governance/governance/collective +--- + +# Collective Overview + +## Purpose + +The Obol Collective’s governance system has two primary goals: + +1. **Resource allocation.** Allocate resources effectively to support the Collective’s vision and grow the Obol Collective's sustainable value. Long-term vision may sometimes conflict with short-term value creation; thus, governance requires a blend of short-term and long-term thinking to allocate the token treasury and protocol revenue effectively. +2. **Capture resistance.** Governance plays a key role in securing the anti-capture and censorship resistance of the Obol Collective. Governance should: + 1. make it possible for operations to continue over the long term without reliance on any individual entity; + 2. prevent any one entity or small group of entities from being able to control or censor. + +## Overview: The Obol Token House and RAF + +Two houses govern the Obol Collective: the Token House and the Obol RAF. + +In the **Token House,** OBOL Token holders are responsible for submitting, deliberating, and voting on governance proposals using the Governance Portal. Token holders can delegate their OBOL Token voting power to their own address or an eligible third party. Addresses with delegated voting power are called “Delegates”. + +In the **Obol Retroactive Fund (RAF)**, OBOL Token Delegates are responsible for allocating funds within the RAF to projects and teams that provide value to the Obol Collective. + +All OBOL holders and Delegates are expected to exercise their authority responsibly and follow the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. + +![](/img/gitbook/image-51.png) + +## The Security Council + +The Security Council is a committee of multi-sig wallet signers with the power to perform certain emergency actions as delegated to it by the Obol Association. + +The Security Council can execute any software upgrade or perform other emergency actions without delay to respond to a security emergency, should one arise. The Security Council must not use its power to perform Emergency Actions except in a true security emergency, such as a critical vulnerability that could significantly compromise the Obol Collective. + +After taking any Emergency Action, the Security Council must issue a full transparency report (at an appropriate time after the security emergency has passed) explaining what was done and why such action was justified. + +## Administration and Implementation + +In all cases, Obol Collective governance is intended to be carried out in a manner consistent with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. The Obol Association will steward this process as described below, with the goal of increasingly decentralising its role over time. + +The Obol Association, via its governance administrators, will facilitate administration to ensure that anyone may participate thoughtfully in governance. Such administrative services may include: + +* Moderation of governance proposals to ensure they are validly submitted and voted upon; +* Removal of proposals that reasonably appear to be fraudulent, spam-oriented, defamatory, hateful, or otherwise inappropriate or inconsistent with the values of the Collective; +* Monitoring of votes, voting power, the votable token supply, and voting periods for purposes of determining whether quorums and approval thresholds are met or accurately reflected; +* Management of mutually contradictory or duplicate proposals that are submitted simultaneously or close to one another; +* Maintenance of the Governance & RAF Portal; +* Other tasks that the Obol Association deems appropriate in connection with the above. + +The Association may also intervene operationally when necessary to uphold the integrity of the governance process — for instance, by removing improperly submitted proposals or enforcing community-agreed rules. When doing so, it will always act transparently and share justifications with the community. + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal or chosen RAF recipients, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails, coupled with an explanation. + +## Vision for Fully On-Chain Governance + +Once Collective’s governance develops and is deemed as sufficiently mature by the Obol Association, the implementations of passed proposals will follow full on-chain execution, where possible. Instead of the Collective’s reliance on the Obol Association for implementation, passed proposals will be moved to a queue to prepare for execution. The queue action will send the proposal to a Timelock contract, which starts a countdown until the proposal can be executed. + +Executing a proposal will run its function calls on-chain. Each proposal can be associated with one or more function calls. These calls will perform actions such as transferring assets from the treasury, updating the Governor's parameters, or calling another smart contract. diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/delegate-guide/README.md b/versioned_docs/version-v1.5/community-and-governance/governance/delegate-guide/README.md new file mode 100644 index 0000000000..27f3067048 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/delegate-guide/README.md @@ -0,0 +1,33 @@ +--- +description: "Delegate Guide" +sidebar_label: "Delegate Guide" +slug: /community-and-governance/governance/delegate-guide +--- + +# Delegate Guide + +## Delegate Rules of Engagement + +This document outlines the expectations, responsibilities, and values that should guide interactions within the Obol Collective governance community, including the Obol Forum, Discord, and working group meetings. This Code of Conduct will be reviewed periodically to incorporate feedback and adapt to governance needs. Any changes require community approval through the governance process. + +Please review these principles carefully to ensure alignment with the Obol Collective’s vision and commitment to a decentralized and sustainable ecosystem. + +Please read the rules of engagement on the forum [here](https://community.obol.org/t/delegates-rules-of-engagement/206). + +## **Governance Toolkit** + +These tools or their uses may change over time as governance evolves. For example, additional user interfaces dedicated to governance may be developed. Likewise, while voting currently takes place on-chain through the Governance Contract, some successful votes are administered and implemented by the Obol Association, which should not be the case indefinitely. + +Please see the toolkit on the forum [here](https://community.obol.org/t/governance-toolkit/207). + +## Delegates’ Role in the RAF + +The role of Delegates in the RAF is to allocate votes to projects that have made substantial positive impact on the Obol Collective’s Decentralized Operator Ecosystem. Vote allocation is proportional to the Delegates’ delegated power. To determine the funding amounts, the [quadratic funding](https://qf.gitcoin.co/) mechanism is used, to ensure a balanced and equitable distribution of influence. + +Visit read [the delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) on the forum. + +## Delegate Compensation + +Starting August 2025, active delegates will be eligible for compensation based on their participation and contributions. This is determined using the **Delegate Reputation Score (DRS):** a scoring system that evaluates each delegate’s voting, rationale, and forum activity. Only delegates with a score of **65 or higher** will qualify for rewards. + +For full details on DRS and how compensation works, see the [Delegate Reputation Score & Compensation page.](delegate-reputation-score-and-compensation.md) diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md b/versioned_docs/version-v1.5/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md new file mode 100644 index 0000000000..99e64d77f0 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md @@ -0,0 +1,97 @@ +--- +sidebar_label: "Delegate Reputation Score & Compensation" +slug: /community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation +--- + +# Delegate Reputation Score & Compensation + +As the Obol Collective moves toward more mature governance, we are introducing a new system to help improve delegate accountability and guide token holder decisions: the **Delegate Reputation Score (DRS)**. + +This mechanism is part of a broader initiative to evolve token governance beyond simple vote counts but toward systems that reward quality participation and reinforce long-term alignment. + +The Obol Collective is among the first DAOs to integrate this model, developed in collaboration with [Tally](https://www.tally.xyz/) and [Curia](https://obol.curiahub.xyz/delegate), helping to pioneer a new standard for **reputation-backed delegate governance**. + +## What is the Delegate Reputation Score (DRS)? + +The Delegate Reputation Score is a reputation system. It gives each delegate a score from 0 to 100 based on their behavior across three core dimensions: + +* **Voting participation** +* **Forum rationale submissions** +* **Forum engagement (discussion and replies)** + +These inputs are tracked over a rolling window of proposals, with scoring updates happening after [every **governance cycle** (every 21 days)](../token-house.md#token-house-governance-proposal-process). The current scoring logic can be found in full detail on [Curia’s documentation](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f), which also serves as the canonical source of truth. + +:::tip +**When does my DRS update?**\ +Scores are updated every 21-day governance cycle, but with a 6-day delay after the submission window closes.\ +This ensures all proposals, including those submitted just before the deadline, have completed their full voting period before scores are recalculated. This buffer guarantees consistency and fairness across the cycle. +::: + +Delegates can view their scores, and token holders can browse and filter delegates based on their reputation and activity levels directly on [Tally](https://www.tally.xyz/gov/obol/delegates). + +### Why it matters + +The DRS is designed to: + +* Help token holders delegate more effectively, with clearer visibility into how delegates are behaving +* Increase accountability by making governance activity measurable and comparable +* Reinforce quality and trust within the delegate set + +In practice, this means token holders are strongly encouraged, through the UI and incentive systems, to **delegate to high-DRS delegates**, while delegates are incentivized to maintain an active and transparent presence in the Collective’s governance. + +_**This is not just a dashboard feature. DRS has real consequences for rewards and visibility.**_ + +### Delegate Statuses by DRS + +Delegates can fall into different categories based on their Delegate Reputation Score (DRS), which is recalculated after every governance cycle. These statuses help token holders understand delegate behavior and make informed delegation decisions: + +* Active: Delegates with a DRS ≥ 65 are considered _active. T_his is the ideal status. Active delegates are eligible for compensation and prominently displayed in the UI to encourage token holders to delegate to them. + * Active (New): A delegate with a DRS ≥ 65 but who has participated in fewer than 5 proposals. While still considered active, this tag highlights that the delegate is relatively new, and their track record is limited. +* Inactive: Delegates with a DRS < 65. These delegates have either skipped votes or failed to post rationales, indicating lower governance engagement. + * Inactive (New): New delegates (fewer than 5 proposals) whose early participation has not met the DRS threshold. This tag signals limited history and insufficient engagement so far. +* Ghost: Delegates who have received voting power but have never participated in any governance vote. Once they vote on a proposal, they’ll transition into an active or inactive status depending on their initial DRS, and will also carry the “new delegate” tag until they surpass 5 evaluated proposals. + +### Bootstrapping New Delegates + +To avoid penalizing new contributors, DRS includes a bootstrapping mechanism. A delegate’s first vote will trigger their scoring process, and their initial DRS will be calculated based on that single proposal. Over time, the DRS evolves into a moving average across the last 5 proposals they were eligible to vote on. This ensures: + +* New delegates who actively participate from the start can achieve a high DRS immediately +* Inconsistent delegates see their score adjust quickly +* A consistent track record is required to maintain an active status + +Additionally, new delegates will be visibly tagged as such in the UI, signaling that their DRS is based on limited history. This helps token holders assess delegation options with full context and encourages early but consistent engagement. + +This design balances the need to reward early participation while preventing score manipulation. Active delegates (even if new) become eligible for compensation as soon as they meet the DRS threshold. + +## Delegate Compensation + +_Delegate Compensation is not live yet. It is scheduled to launch in the second part of August 2025._ + +We are also introducing **delegate compensations**, funded by the Delegate Rewards Pool. Compensation is **gated by DRS**: only delegates with a score of **65 or above** are considered “active” and eligible. + +Once classified as active, rewards are distributed using a **square root model**, based on delegated voting power. This model was selected to strike a balance between influence and fairness: + +* It reduces reward concentration among the largest delegates +* It supports smaller, high-performing delegates +* It helps foster a more pluralistic and sustainable governance ecosystem + +This approach is experimental and will be closely monitored. Over time, we may revisit weighting or distribution methods based on observed outcomes. + +### **Why Delegate Compensation?** + +At Obol, we believe that **no one should work for free. B**ut we also recognize that **not all participation is equally meaningful**. Delegate compensation isn’t about paying people to hold tokens or rubber-stamp votes. It’s about rewarding those who consistently engage with care, post structured rationales, and help the Collective navigate complex governance questions with thoughtfulness and integrity. + +Compensation is now earned through **visible, active contribution —** whether through dissent, alignment, or creative proposals — as long as it’s expressed in a way that moves the Collective forward. Good-faith disagreement and diversity of thought are part of what makes a governance system resilient. That’s the work we want to support. + +## A collaborative standard + +The DRS is a shared initiative between Obol, Tally (UI and standardization), and Curia (calculation and onchain oracle). While the Obol Collective is among the first to adopt this system, the hope is that it will be used by other DAOs seeking to upgrade their delegate models. + +We are proud to help drive this standard forward and will continue sharing learnings as we refine the system in practice. + +## Resources + +* [Tally Delegate Portal](https://www.tally.xyz/gov/obol/delegates) – see live DRS scores, search delegates, and explore participation history +* [Curia Dashboard](https://obol.curiahub.xyz/delegate) – DRS calculation details and complementary metrics +* [Curia's Source of truth for scoring logic](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f) – Broken down calculation of DRS +* [OIP-4: Delegate Compensation & DRS Scoring](https://community.obol.org/t/oip-4-delegate-compensation-and-delegate-reputation-score-integration-for-stobol/522) – original governance proposal diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/README.md b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/README.md new file mode 100644 index 0000000000..0c8fcec898 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/README.md @@ -0,0 +1,85 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/governance/grants-program +--- + +# Grants Program + +_⚠️ The grants program is currently **paused**, as the pilot phase has officially concluded._ + +_We’ve funded a number of initial initiatives and plan to publish a full transparency report on these grants in the coming weeks._ + +_The program is expected to resume in **September 2025** under a new structure, reflecting key lessons from the pilot and offering clearer tracks for community events, protocol integrations, and milestone-based initiatives like the Staking Mastery Program._ + +_Stay tuned for the full relaunch and documentation updates soon._ + +*** + +## **Purpose** + +The Obol Grants Program (pilot) aims to support projects that advance the strategic goals of the Obol Collective by providing milestone-based funding to builders, educators, and contributors working on public goods aligned with the Distributed Validator (DV) ecosystem. + +This program is specifically designed to address the execution of the strategic SQUAD Goals outlined in [OIP-3](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/) that require community involvement. Each grant proposal must clearly align with **one of the grant tracks**, which reflect these goals. The grant tracks help ensure that funds are directed toward work that directly contributes to the Obol Collective's mission. + +To ensure proposals are aligned with these objectives, each track has a dedicated sub-page with: + +* A self-assessment checklist to help determine if the proposal is in scope +* Guidance on the types of contributions and initiatives encouraged +* Detailed evaluation criteria used to assess submissions + +## Structure + +* The program will operate in 8**-week waves**: + * **Application window:** 2 weeks + * **Review & approvals:** 2 weeks + * **Pause to keep track and provide guidance to the new projects**: 4 weeks +* **Milestone-based funding:** Grants are approved as a full proposal, but **funds are released per milestone**, once validated by the committee. Each proposal must define its expected milestones in advance. Applicants will have the opportunity to clearly outline their milestones during the application process. This includes describing the deliverables for each stage of the project and the success criteria for unlocking the next tranche of funding. A step-by-step guide to structuring and submitting milestone-based proposals is provided in a [dedicated sub-page](how-to-create-a-proposal-in-questbook.md). These milestones serve as checkpoints for disbursement and accountability. +* **Grant tracks aligned with** [**OIP-3 SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388)**:** + * [Boosting Obol DV Adoption](grant-track-for-boosting-obol-dv-adoption.md) + * [Establishing OBOL Token’s Role in DeFi & Governance](grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md) + * [Strengthening the Collective: Operators & Community Growth](grant-track-for-strengthening-the-collective-operators-and-community-growth.md) + +> **Funding Disclaimer:**\ +> The OBOL token amount will be calculated based on the USD value of your grant request using the market price of OBOL at the time your proposal is approved. That means the number of tokens may vary depending on the price at the time of approval. + +## Pilot Wave Timeline + +
PhaseDatesNotes
Applications OpenMay 14 – June 11Anyone can apply during this period
Review & ApprovalJune 12 - June 25Committee reviews proposals and approves based on milestone scope.
Publish recap of selected proposals and next steps
Pause & MonitoringJune 26 - July 23Publish recap of selected proposals and next steps
+ +## Platform + +The program will be managed via [Questbook](https://questbook.app), with future integrations possible (Tally, etc). All proposals, reviewer activity, and milestone tracking will be transparent and publicly viewable. + +## Review Process + +* **Initial pilot approval committee**: 2 members from the Obol Association (Leo & Toma) +* **Later stages may expand to a formal committee & Tally-based voting** +* Reviews are rubric-based, and public by default within Questbook. These are structured scoring frameworks that help reviewers assess applications consistently across several criteria, such as: + + * Alignment with grant track and SQUAD goal(s) + * Feasibility and clarity of the milestones + * Potential impact and relevance to the Obol ecosystem + * Team capacity and track record + + Each grant track sub-page includes the specific rubric and criteria relevant to that category. + +## Budget + +* All **funding will be disbursed on a milestone basis only** _(see above disclaimer)_ +* Future quarterly or annual grant budgets to be approved by DAO governance +* The first pilot wave (Wave #1) will not specify any max budget. + +## Communication + +* Public recap of each wave will be posted on the Obol Forum + +## Future Upgrades + +* **Governance voting integration** via Tally +* **Expanded grant committee** with delegate participation +* **AI-assisted review workflows** if shown to increase efficiency + +## Transparency + +* The Obol Grants Program is currently hosted under Questbook's open-source plan +* All activity will remain publicly accessible through Questbook diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md new file mode 100644 index 0000000000..53f15621cc --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption.md @@ -0,0 +1,87 @@ +--- +sidebar_label: "Grant Track for Boosting Obol DV Adoption" +slug: /community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption +--- + +# Grant Track for Boosting Obol DV Adoption + +The following guide will provide you with all the info you need to apply for a grant related to **Boosting Obol DV Adoption**. [You can apply directly on Questbook, here.](https://questbook.app/proposal_form/?grantId=6808de63300aee1f224f930a\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share) + +## Is My Proposal In-Scope for This Grant Track? + +This Grant Track seeks **technical integrations**, **infrastructure tooling**, and **adoption-driven initiatives** that accelerate the adoption of Obol DVs — especially in high-stake sectors like Liquid Staking, Restaking, and Community Squads. + +Proposals are **in-scope** if they: + +* Integrate Obol DVs into staking protocols (e.g. Lido v3, Etherfi, Swell, EigenLayer) +* Launch or grow community squads staking with DVs +* Build tools, dashboards, or deployment frameworks that reduce barriers to DV adoption +* Educate or onboard new users and node operators into the Obol ecosystem + +## Grant Track Priorities & Squad Goals + +This Grant Track hosts the following **Squad Goals** that represent Obol community priorities: + +#### **Category A – Deepen DVs penetration into (Re-)Staking Protocols** + +* Details: Integrate Obol DVs as the infrastructure layer of Liquid Staking & Restaking Protocols. Protocols represent about 37.5% of the Ethereum stake according to [Hildobby’s staking data](https://dune.com/hildobby/eth2-staking). Obol DVs currently [represent about 2%](https://obol.org/dashboard) of that stake. Example workstream: Collaborations with top protocols existing and new products (e.g., Lido v3, Etherfi eETH, Swell rswETH). +* Success Metrics: Make Obol DVs 10% of the Protocols Stake share. +* Exemples: + * Integrate Obol DVs into a Liquid Staking or Restaking protocol + * Build SDKs, APIs, or plugins that simplify DV integrations for protocols. + * Deployment scripts, wrapper contracts, REST APIs, infra automation tools + +#### **Category B – Deepen DVs penetration with community squads** + +* Details: Launch more community squads across the globe. Continue building launcher tooling and educational content on DVs to make squad staking easy. Currently Obol community squads run about 15,000 ETH. Example workstream: Programs to assist new node operators in setting up and fund Obol DVs. +* Success Metrics: + 1. 20 new community squads + 2. 25,000 ETH running on Obol DVs. +* Exemples: + * Create launcher tooling or deployment guides to enable squads. + * Run educational campaigns, community events, or node operator bootcamps + * Build dashboards, docs, or user-facing UX that reduces DV friction. + +## Milestone Articulation + +Grants in this track will be disbursed based on **clear, outcome-oriented milestones**, ideally aligned with measurable KPIs. + +Competitive grant requests include **3–5 milestones**, such as: + +* Signed protocol integration commitment +* Live testnet deployment +* Mainnet launch with DV cluster +* Target stake threshold hit (e.g., 1,000 ETH in DVs) +* Community feedback, docs, or case studies + +> 💡 Milestones should include both technical outcomes and adoption-based KPIs. + +## Security & Audit Requirements + +Proposals involving smart contract deployments must: + +* Document contracts clearly in the proposal +* If relevant, undergo audit from a reputable third-party auditor (e.g., Dedaub, ChainSecurity) +* Include audit as a funded milestone +* Complete audit before any mainnet funds are disbursed + +*** + +## What Makes a Strong Grant Request? + +* **Clear Impact**: Shows a measurable path to DV adoption across a protocol, institution, or community +* **Strong Team**: Has relevant experience in staking, infra, or validator tech +* **Ecosystem Fit**: Aligns with Obol's decentralization and resilience mission +* **Detailed Milestones**: Tied to real-world outcomes, not just deliverable completion +* **Sustainable Plan**: Long-term support considered (infra, community, updates) + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Applies To** | **Criteria** | +| ----------------------- | ----------------------- | ----------------------------------------------------------------- | +| DV Adoption Potential | All domains | How directly does this increase stake running on Obol DVs? | +| Technical Feasibility | Protocols, Institutions | Can this be realistically built by this team? | +| Stake Impact Projection | Protocols, Institutions | How much stake could realistically be secured with this proposal? | +| Ecosystem Alignment | All domains | Is this aligned with Obol's decentralization mission? | +| Milestone Clarity | All domains | Are deliverables concrete, verifiable, and meaningful? | +| Team Credibility | All domains | Does the team have relevant background or traction? | diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md new file mode 100644 index 0000000000..4e02800624 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance.md @@ -0,0 +1,75 @@ +--- +sidebar_label: "Grant Track for Establishing OBOL Token’s Role in DeFi & Governance" +slug: /community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance +--- + +# Grant Track for Establishing OBOL Token’s Role in DeFi & Governance + +The following guide will provide you with all the info you need to apply for a grant related to Establishing OBOL Token’s Role in DeFi & Governance. [You can apply directly on Questbook, here](https://questbook.app/proposal_form/?grantId=6808df2e9ccae779614de4a6\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share). + +## Is My Grant Request In-Scope for This Grant Track? + +This Grant Track focuses on helping OBOL become a **core asset in Ethereum DeFi and protocol governance**, with emphasis on **TGE unlock success**, **on/off-chain liquidity**, and **DeFi integrations**. + +Your proposal is **in-scope** if it contributes to any of the following: + +* Improving liquidity of OBOL/stOBOL on DEXs and aggregators +* Deploying stOBOL as collateral or governance asset in DeFi protocols +* Developing tools, bridges, dashboards, or data integrations for OBOL +* Enhancing token UX or reputation (e.g. Chainlink oracles, analytics) + +> While the TGE and unlock strategy is centrally executed by the Obol Association, the community is encouraged to support OBOL's DeFi path via proposals, integrations, and partnerships. + +## Grant Track Priorities & Goals + +#### **Category A – Deep Liquidity & Market Presence** + +* Details: Provide ample liquidity so that participants can easily trade in and out of (st)OBOL. This ensures market confidence in the token being able to trade large volumes and sustain swings in price actions without too many negative effects such as slippage. +* Metrics: + * Deploy stOBOL as collateral on one Top 10 TVL DeFi Protocols (e.g. Morpho) +* Exemples: + * Design & deploy a stOBOL liquidity vault on Arrakis, Balancer, or Maverick + * Propose DAO-level liquidity incentives across DeFi venues + * Gauge votes, flywheels, or incentive co-funding with protocols. + * Deploy stOBOL as collateral in a major DeFi protocol + * Morpho, Aave, Compound, or FraxLend. Proposal should outline required steps (audits, onboarding, etc). + * Build integrations, bridges, or tools for token usability + * Token routers, zap tools, multi-chain bridges, UI UX support for using OBOL/stOBOL. + +## Milestone Articulation + +Grants will be disbursed based on **milestone-based funding**, with a focus on **liquidity outcomes**, **integration readiness**, and **community activation**. + +Typical milestones may include: + +* Smart contract deployment (vault, adapter, collateral wrapper) +* Governance proposal submission and/or approval +* Integration live on testnet/mainnet +* Trading volume or liquidity KPIs achieved (e.g. $1M TVL, $500K 30D volume) +* Community feedback incorporated or UI launched + +> Aim to tie final milestones to live integrations or measurable liquidity metrics. + +## Security Requirements + +* Smart contract deployments must be audited or forked from audited sources +* Where necessary, coordinate audits with the Obol Association +* Audit completion must be a milestone for DeFi protocol integrations + +## What Makes a Strong Proposal? + +* **Strategic Fit**: Aligns directly with OBOL’s token vision (see OIP-1 & OIP-2) +* **Credible Team**: Strong DeFi, token, or liquidity experience +* **Tangible Outcomes**: Focus on integrations, liquidity depth, or real utility +* **Governance Aware**: Engages with DAO or DeFi governance in a thoughtful way +* **Long-Term View**: Includes sustainability considerations (e.g. vault maintenance, fee-sharing) + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| --------------------------- | ---------------------------------------------------------------------------- | +| **Team Experience** | Demonstrates ability to execute in DeFi, integrations, or token infra | +| **Impact Potential** | Adds liquidity, unlocks new use cases, or supports long-term token utility | +| **Feasibility** | Proposal is technically and strategically realistic within a 3–6 month scope | +| **Alignment with Strategy** | Advances OBOL as a governance or collateral asset per OIPs & roadmap | +| **Clarity & Milestones** | Milestones are specific, measurable, and adoption-oriented | diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md new file mode 100644 index 0000000000..a9be8a9bb5 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth.md @@ -0,0 +1,73 @@ +--- +sidebar_label: "Grant Track for Strengthening the Collective: Operators & Community Growth" +slug: /community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth +--- + +# Grant Track for Strengthening the Collective: Operators & Community Growth + +The following guide will provide you with all the info you need to apply for a grant related to Strengthening the Collective: Operators & Community Growth. [You can apply directly on Questbook, here](https://questbook.app/proposal_form/?grantId=6808e08e9ccae779614e2cfe\&chainId=10\&utm_source=questbook\&utm_medium=grant_details\&utm_campaign=share). + +## Is My Proposal In-Scope for This Grant Track? + +This Grant Track funds work that builds **capabilities and coordination** within the Obol ecosystem — especially among distributed validator operators and active Collective members. + +You’re likely in-scope if your proposal: + +* Trains, certifies, or supports DV operators in joining Obol clusters +* Improves the Silver Techne onboarding experience, curriculum, or support +* Builds infrastructure, guides, or dashboards to track operator activity or status + +Whether you’re focused on operator growth, or ecosystem education — we want to hear from you. + +## Grant Track Priorities & **Goal**s + +#### **Category A – Operator Development (Silver Techne)** + +* Details: Train and certify a professional class of operators who can scale networks reliably by running Obol DVs. Currently there is [about 600 Silver Techne credentials](https://etherscan.io/token/0xfdb3986f0c97c3c92af3c318d7d2742d8f7ed8cc). +* Success Metrics: Grow the number of Silver Techne Credentials by 30%. +* Exemples: + * Design or improve training content for Silver Techne + * Docs, videos, interactive workshops, validator testnets + * Build or enhance certification workflows and dashboards + * UX to issue/review credentials, operator leaderboards, cluster-readiness tools + * Regionalize operator onboarding programs + * Language localization, timezone-based support, squad coordination templates + +> These proposals should prioritize transparency, inclusion, and fair access for contributors. + +## Milestone Articulation + +Grants are paid out in **staged milestones** that reflect real-world progress and value delivered to the operator ecosystem or community. + +Examples of strong milestones: + +* Training curriculum published, piloted with 20 new operators +* 50+ new Silver Techne credentials issued (with wallet verification) +* Launch of open project board with real-time community activity + +## Security & Credibility Notes + +Grant Requests that touch credentialing, access controls, or public dashboards must: + +* Respect contributor privacy and security +* Be reviewed by at least one Collective contributor for community fit +* Prioritize open-source and reproducible tooling wherever possible + +## What Makes a Strong Grant Request? + +* **Community Fit**: Proposal aligns with Obol’s mission of decentralization and collective stewardship +* **Operator Support**: Drives real growth in the Silver Techne operator pool or quality of operator experiences +* **Transparency**: Proposes open processes, accessible documentation, and easy participation +* **Sustainability**: Suggests systems that can scale or run with community ownership +* **Clear Value**: Tied to quantifiable growth in contributions, certifications, or community activity + +## Evaluation Rubric (0–5 points per category) + +| **Category** | **Description** | +| ------------------------- | -------------------------------------------------------------------------------- | +| **Team Experience** | Is the team familiar with validator ops, contributor tools, or community design? | +| **Impact Potential** | Will this grow or support long-term contributor or operator engagement? | +| **Technical Feasibility** | Is the proposal scoped realistically and implementable with the given resources? | +| **Milestone Clarity** | Are there measurable indicators of success and clear timelines for each phase? | + +\ diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md new file mode 100644 index 0000000000..2e199ee00a --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook.md @@ -0,0 +1,90 @@ +--- +sidebar_label: "How to create a proposal in Questbook?" +slug: /community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook +--- + +# How to create a proposal in Questbook? + +This guide walks you through the full process of preparing and submitting a grant proposal to the Obol Grants Program using [Questbook](https://questbook.app). + +### 1. Respect the Wave Schedule + +Each grant wave follows a strict timeline. Grant requests must be submitted during the **application window** listed in the [Grants Program page](./#structure). + +> ⚠️ Proposals submitted outside of an open wave window will **not** be considered. + +*** + +### 2. Choose the Right Grant Track + +Your grant request must clearly align with **one of the three main grant tracks**, which are tied to the Obol Collective's SQUAD goals. Each track has its own page with: + +* Scope verification checklist +* Expectations and contribution types +* Evaluation criteria used during review + +_**On each grant track page, you will find the link to apply for that specific track on Questbook.**_ + +👉 Visit the grant track guides linked [here](./#structure). + +*** + +### 3. Prepare to Submit on Questbook + +#### If you don't already have a Questbook account: + +* Go to [https://questbook.app](https://questbook.app) +* Create a new wallet or connect an existing one +* Back up your wallet's private key securely — you will need it to access your account + +*** + +### 4. Create Your Application + +1. Select the grant **track** aligned with your grant request and follow the link provided in the dedicated subpage +2. Complete each section of the form, including: + * Project summary + * Team & track record + * Grant track alignment + * Milestones & timelines + * Requested funding & deliverables per milestone + +Each section is pre-structured to guide you in providing the expected information. + +*** + +### 5. Include Your Cost Breakdown + +You must attach a cost breakdown using the **template provided by the Obol Association** (linked below). + +* You may modify the structure, add/remove rows, or use your own format if clearly structured. +* Make sure costs are tied to **milestones**, not just a lump sum. + +👉 [Download the cost breakdown template here](https://docs.google.com/spreadsheets/d/10QoterGwLTZyeCf8yShOuGOaLybJd23qrzHnd28J7AM/edit?usp=sharing) + +*** + +### 6. Post in the Forum + +Once your application is submitted on Questbook: + +* Go to the [**Obol Grants Forum Thread**](https://community.obol.org/t/obol-grants-wave-1-submissions-thread/525) +* Post a comment with: + * Your project name + * A short summary + * A link to your Questbook grant request + +This ensures community visibility and transparency. + +*** + +### 7. What Happens Next + +* During the review period (after the wave closes), your grant request will be evaluated by the current committee. +* Reviews will use the rubric published in your track’s page to evaluate your request. +* Feedback may be shared on Questbook or through the forum. + +**If approved:** + +* You’ll be contacted for milestone validation and next steps for funding. +* Disbursements will occur **after milestone delivery is validated.** diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/raf/README.md b/versioned_docs/version-v1.5/community-and-governance/governance/raf/README.md new file mode 100644 index 0000000000..ef76292720 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/raf/README.md @@ -0,0 +1,76 @@ +--- +description: "The RAF" +sidebar_label: "The RAF" +slug: /community-and-governance/governance/raf +--- + +# The RAF + +Obol’s Retroactive Funding (RAF) mechanism is designed to strengthen and promote the decentralisation of Ethereum's settlement layer by rewarding projects that add value and drive impact for Ethereum’s decentralisation. Read more about the Obol RAF [here](https://blog.obol.org/1-percent-for-decentralisation/). + +Voting and funding distributions occur over a series of **Obol Retroactive Fund (RAF)** rounds, with OBOL token Delegates determining how funds from the RAF are allocated. The first RAF round will open in February 2025. + +## Overview of the Obol RAF: + +* Any project that meets the RAF round’s criteria can make an application. +* OBOL Token Delegates vote on applications proportional to their delegated power and using [quadratic funding](https://qf.gitcoin.co/). +* The Obol RAF rounds occur at intervals and include phases for scoping, application creation, application review, voting, and funding distribution. +* The Obol Association will collect information from projects to distribute grants, including KYC, where required. + +Below is described the steps within each RAF round. Each step takes approximately one week.\\ + +![](/img/gitbook/image-53.png) + +### Step 1: Scoping + +The scope of the round’s impact and the amount of funding to be allocated is defined by the Obol Association at the outset of the round and posted on the Obol Forum. + +### Step 2: Application Registration + +Projects are invited to create an application on the [RAF App](http://raf.obol.org/). Any project or team can apply, but in the future, governance may decide that an application needs to be made by someone holding a minimum amount of OBOL tokens. + +Once a RAF round is opened, to apply for the Obol RAF, projects can create an application on [raf.obol.org](http://raf.obol.org/) by following these steps: + +1. **Create an Application:** Fill out the application form using the [RAF App](http://raf.obol.org/). +2. **Describe Impact:** Specify the category of the project and its impact. + +### Step 3: Application Review + +A subset of OBOL Delegates appointed by the Obol Association reviews applications to ensure compliance with the application rules. + +The Obol Association will also review applications to filter out spam or applications that do not align with the mission of the Obol Collective. + +### Step 4: Voting + +OBOL Delegates vote on projects in proportion to their voting power. Here’s how it works: + +1. **Eligibility:** Every address that has been delegated voting power by OBOL Token holders can submit votes. +2. **Voting Process:** Delegates vote using the [raf.obol.org](http://raf.obol.org) app. Depending on the type of application being reviewed, a specific set of criteria should be used to judge a project's contributions to the Obol Collective. + +:::warning +The Obol Association will monitor votes to ensure contributors are not voting for projects they are directly involved in or where a substantial conflict of interest may be present. Delegates are expected to act in accordance with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. +::: + +### Step 5: Tallying Results + +The voting power of each OBOL Token Delegate is proportional to the amount of OBOL tokens delegated to them. However, the funding results are calculated using [quadratic funding](https://qf.gitcoin.co/), meaning that the square root of the votes is used to determine the final allocation. This approach ensures a broader distribution of funding across the Obol Collective, rather than allowing a small number of winners to dominate. + +### Step 6: Compliance + +The Obol Association will review the list of selected projects, adjust if necessary and collect information from them to distribute the grant legally compliantly (including completing KYC if required). + +### Step 7: Funding distribution + +The overall reward amount for the round is divided among the winning projects based on the delegates' vote and allocation according to the quadratic funding mechanism. + +### **Step 8: Community retrospective** + +After each round, The Obol Association will conduct a retrospective and gather community feedback. + +## Guides for each Round + +RAF1: see the [RAF1 guide](https://community.obol.org/t/guide-for-raf-round-1-raf1/227) in the forum. + +## RAF1 Summary & Insights + +Head over to [raf1-guide.md](raf1-guide.md "mention") to find the results, top projects, and key takeaways from our first round. diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/raf/raf1-guide.md b/versioned_docs/version-v1.5/community-and-governance/governance/raf/raf1-guide.md new file mode 100644 index 0000000000..0acc913186 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/raf/raf1-guide.md @@ -0,0 +1,27 @@ +--- +sidebar_label: "RAF #1" +slug: /community-and-governance/governance/raf/raf1-guide +--- + +# RAF #1 + +## Learnings from RAF Round 1 + +Our first Retroactive Funding round (RAF1) awarded 1 million OBOL to 46 projects using a quadratic voting mechanism. Projects were evaluated on technical impact, contribution to decentralization, and public goods alignment. + +### Top-funded projects included: + +* Dappnode — integrated Obol into their Dappstore, enabling 16k+ validators to use Obol setups. +* Ethereum on ARM — ran distributed validators on low-cost devices. +* Stereum — offered one-click node deployment with Obol pre-installed, backed by strong GitHub and beaconcha.in adoption metrics. + +### Key learnings: + +* Impact evaluation is challenging without clear data; future rounds may require stronger entry thresholds. +* Quadratic voting worked to elevate broadly supported projects, but needed clearer onboarding. +* Delegates requested better UX for wallets and real-time visibility into vote progress. +* Community engagement was strong but limited in feedback volume — improving outreach will be a focus + +_**We’re using these insights to shape future RAF rounds, with an emphasis on transparency, fairness, and long-term ecosystem impact.**_ + +👉 [Read the full blog post here](https://blog.obol.org/raf1-results/) diff --git a/versioned_docs/version-v1.5/community-and-governance/governance/token-house.md b/versioned_docs/version-v1.5/community-and-governance/governance/token-house.md new file mode 100644 index 0000000000..25a60f8ed3 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/governance/token-house.md @@ -0,0 +1,121 @@ +--- +description: "The Token House" +sidebar_label: "The Token House" +slug: /community-and-governance/governance/token-house +--- + +# The Token House + +In the Token House, OBOL Token holders are responsible for submitting, deliberating, and voting on various Obol Collective governance proposals. + +## Overview of the Obol Token House + +* Proposals are reviewed and voted on in three-week cycles. + +:::info +You can subscribe to the public calendar [here](https://calendar.google.com/calendar/u/0?cid=Y183YzQ0ZmYwZjM5ODE4ZTcyODg2OTM2MmI4ZWEyMGNmMDdhMmZmMmZiMzMxYjE2MjMwYzg3ZjQxZGRiYjA4N2ViQGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20\&ref=blog.obol.org) so you always know where the current cycle stands. +::: + +* In the first week, anyone may draft a proposal of any type based on [this template](https://community.obol.org/t/proposal-template/208) and post it on the [Forum](https://community.obol.org/) with \[Draft] in the title. Delegates, Obol Collective members, and the general public can provide feedback on proposals in the forum, which should be incorporated into the proposal using the author’s best judgment. +* Once your proposal has been approved by four top-100 Delegates (by voting power), add a link to your proposal to the Voting Cycle Roundup forum thread by the last day of Week 2, and update the title from \[Draft] to \[Final]. The proposal then moves on to Week 3: Voting. +* If your proposal is passed, the Obol Association will facilitate its administration, including distributing approved OBOL Tokens grants. +* If your proposal fails, you can make a new proposal in the next cycle, specifying how you have incorporated significant changes from your first proposal.\\ + + ![](/img/gitbook/Token_house.png) + +## Token House Governance Proposal Process + +Anyone can submit a proposal to the Token House by using the Governance Portal. Proposals are accepted or rejected using a voting process. A proposal must be one of the valid proposal types listed below and follow the voting process described here. + +All governance proposals go through a 3-week cycle. Each “week” runs from Thursday at 7:00 pm GMT until Wednesday at 7:00 pm GMT. + +### Valid Proposal Types + +All governance proposals must fall within one of the following categories: + +* Ecosystem grants +* Protocol upgrades +* Token inflation adjustment +* Treasury allocations +* Work agreements +* Veto on the Obol RAF operations + +The different requirements for submission and approval of each Proposal Type are summarized below. If a specific template is not specified below, proposals should follow this standard proposal template. + +All Ecosystem grant applications are processed by the Association. + +Below are listed types of Token House Proposals. Each has a two-week review period plus one week voting window, with an approval threshold of 51%. + +| Proposal Type | Description | Submission Requirements | +| :-----------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------- | +| Ecosystem grants | The Obol Association’s treasury may be used to support development of the Collective and/or growth of the ecosystem via the proposal template. | Forum proposal + On-Chain Voting | +| Token inflation adjustment | Changes to the OBOL Token Contract or its supply. | Forum proposal + On-Chain Voting | +| Treasury Appropriations | The amount of OBOL Tokens the Obol Association may spend or distribute annually | Proposal initiated by the Association + On-Chain Voting | +| Work agreements | Formal arrangements between the Obol Association and contributors, teams, or organizations tasked with advancing specific initiatives or responsibilities within the ecosystem | Forum proposal + On-Chain Voting | +| Veto on the Obol RAF operations | The veto mechanism serves as a safeguard against decisions or actions within the RAF operations that are misaligned with the mission of decentralization, transparency, or the collective interests of the community. | Forum proposal + On-Chain Voting | +| Protocol upgrades | Scheduled changes to the on-chain smart contracts comprising the protocol or governance contracts. | Forum proposal + On-Chain Voting | +| SQUAD Goals | It reflects the aim of establishing shared, strategic, and community-driven objectives. Goals are set annually, with each cycle beginning in April. | Forum proposal + On-Chain Voting | + +### Weeks 1-2: Feedback and Review + +All proposal types should be posted to the [Obol Forum](https://community.obol.org/) for review. Proposal authors are expected to respond to feedback from Obol Collective members and Delegates. + +Proposals should be: + +* Submitted as a new discussion thread on the [Governance Forum](http://community.obol.tech/) in the appropriate Proposal Category. +* Marked with \[Draft] in the title. +* Formatted and contain information consistent with the [standard proposal template](https://community.obol.org/t/proposal-template/208). + +Before the end of Week 2, a governance administrator will create a Voting Cycle Roundup thread in the forum summarising all the proposals that meet the voting requirements for Week 3 Voting. + +For proposals to proceed to Week 3, four of the top 100 delegates by voting power must give explicit approval on the discussion thread. Delegates may signal approval by pasting the following comment on the proposal discussion thread: _”I am an Obol Delegate \[link to your delegate commitment in your Tally profile] with sufficient voting power, and I believe this proposal is ready to move to a vote."_ + +If a Delegate approves a proposal to move to a vote, it does not endorse that proposal. It simply signifies that they believe the proposal is ready to move to a vote. + +After receiving the required approvals, the author should update the proposal title from \[Draft] to \[Final] and add a link to their proposal in the Voting Cycle Roundup thread by the last day of Week 2 at 19:00 GMT. Authors should also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal’s progress. Proposal authors should include relevant links if feedback was gathered outside the Forum (e.g., on Discord). + +If a proposal author does not get explicit approval or wants more time for feedback, they should not include their proposal in the Voting Cycle Roundup thread. Instead, they should continue to seek community feedback and submit an updated proposal in the next voting cycle. + +:::warning +If a proposal that did not receive explicit approval through the steps above is submitted to the voting portal, the Obol Association reserves the right to cancel it onchain. While the Association is currently working to formalize this cancel authority within the Governor contract, this measure helps preserve governance integrity and ensures that only properly vetted proposals are voted on. +::: + +### Week 3: Publish a Proposal Onchain and Voting + +During Week 3, a wallet holding at least [30,000 OBOL in voting power](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c#readContract) must publish the proposal on the [Obol Governance Platform](https://www.tally.xyz/gov/obol).\ +After publication, there is a 24-hour voting delay, during which the proposal can be canceled if necessary. The voting delay is the amount of time between when a proposal is submitted and when it goes up for voting. The delay gives token holders time to delegate their voting power before the vote starts or buy more votes. Governor takes a snapshot of all the voting power at the start of voting. Read more [here](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/how-to-pick-governor-parameters#how-to-pick-the-voting-delay). + +:::warning +Important: Any proposal published on Tally must exactly match the version approved by top delegates on the forum—word for word. Adding new elements that were not explicitly approved is strictly forbidden. Additionally, proposal authors must keep the first post of the forum thread updated to reflect the latest version, so readers don’t have to search the comment section for changes. +::: + +\ +After the 24 hours, Delegates (including OBOL Token holders who have self-delegated) vote on proposals via the [Obol Governance Portal](https://vote.obol.org/). All proposals are included in voting if they were added to the Voting Cycle Roundup thread before the deadline and have the approval of four top-100 delegates. + +A governance proposal is **approved** if it satisfies two requirements: + +* **Quorum:** A minimum number of OBOL Token votes measured as _a % of the total votable OBOL Token supply, as of the start of the voting period._ “Votable supply” is the total amount of OBOL Tokens that have been delegated (including to oneself) and, therefore, can participate in voting. The current definition for the OBOL Token House is 0.84% of minted supply. +* **Approval threshold:** The minimum _% of votes cast in support relative to the total number of votes._ The current definition for the OBOL Token House is 0.01% of minted supply. + +A snapshot is taken at the start of each voting period to determine each delegate’s voting power. Voting is hosted on the Obol Governance Portal. + +If a proposal is submitted for a vote and does not pass, the proposal will not be executed. If a proposal author wishes to iterate on a rejected proposal, they should: + +1. Create a new proposal thread on the Forum. +2. Include a link to the first proposal that did not pass. +3. Clearly identify what has changed in the new proposal. + +:::warning +If the same proposal fails to pass two consecutive times (i.e., it is rejected onchain twice in a row), it may not be reintroduced or submitted again for a minimum period of 5 **governance cycles** — roughly equivalent to 3.5 **months** (based on the current 3-week cycle length). This ensures that only well-formed, broadly supported proposals proceed and discourages repeated cycling of the same topic without meaningful revision or support. +::: + +### Timelock Delay + +After the voting period ends, if the proposal passes, there will be a 5-day timelock delay. The timelock delay is the minimum time required between the approval and execution of a proposal. This delay gives stakeholders a final opportunity to review and react before the proposal is implemented. Read more [here](token-house.md#implementation). + +## Implementation + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails. diff --git a/versioned_docs/version-v1.5/community-and-governance/obol-token/README.md b/versioned_docs/version-v1.5/community-and-governance/obol-token/README.md new file mode 100644 index 0000000000..7ea434d6e6 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/obol-token/README.md @@ -0,0 +1,105 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/obol-token +--- + +# The OBOL Token + +The OBOL Token is central to the governance and operation of the Obol Collective. It serves multiple purposes that are essential to its functioning. + +**OBOL Token Transferability:** With the approval of[ OIP-2](https://community.obol.org/t/oip-2-unlock-obol-token/317/30), the OBOL Token is set for a strategic and well-planned unlock. The tokens will be unlocked on the 7th May 2025 at 11:00 UTC, following the completion of centralized exchange listings. Please go to [claim.obol.org](https://claim.obol.org) to unlock airdrop tokens. + +## Token Contract + +The official token contract address of the OBOL Token is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7) + +## Official Uniswap Pool + +The official Uniswap Pool for the OBOL Token is [https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434](https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434) + +## Verified Contract Addresses {#verified-contract-addresses} +The following smart contracts power OBOL staking, governance, and reward distribution on Ethereum mainnet. + +
+ +Governor Contract + +* **Address:** [`0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c`](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c) + +- **Purpose:** Manages onchain proposal lifecycle and voting logic for Token House governance. +- **What you can find onchain:** + * Voting thresholds + * Quorum settings, + * Delay/period configs, + * Proposal and vote history. + +
+ +
+ +Obol Staker + +* **Address:** [`0x30641013934ec7625c9e73a4D63aab4201004259`](https://etherscan.io/address/0x30641013934ec7625c9e73a4D63aab4201004259) + +- **Purpose:** This is the base layer of the Obol staking system. It facilitates the basic mechanics of staking, such as managing deposits, forwarding governance delegation, and streaming rewards based on earning power. +- **What you can find onchain:** + * Total OBOL staked in the contract + * Stake, earning power, rewards and balances on a granular, per-deposit basis + * Current reward rate and configuration + * Contract events (e.g. `Staked`, `Withdrawn`) + * Interactions for staking/unstaking + +
+ +
+ +stOBOL (ERC-20 Token Contract) + +* **Address:** [`0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC`](https://etherscan.io/address/0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC) +* **Purpose:** A liquid ERC-20 representation of staked OBOL built on top of the Obol Staker. It adds features like transferability, reward auto compounding, and the ability to use a staked OBOL position in other protocols. Holders retain the ability to delegate their staked tokens to the governance delagate of their choice. +* **What you can find onchain:** + * ERC-20 metadata (name, symbol, decimals) + * Total supply and balances + * Transfer history + * Allowances / approvals + * Voting power interface (via `getVotes` and `delegates`) + * Event logs for delegation changes + +
+ +
+ +Reward Notifier + +* **Address:** [`0x384dd81047F88eE35DE75DA1149943B8e62d8802`](https://etherscan.io/address/0x384dd81047F88eE35DE75DA1149943B8e62d8802) +* **Purpose:** Manages the distribution of tokens to the staking contract so they can be streamed as rewards to stakers. +* **What you can find onchain:** + * Current and past reward rate values + * Administrative role settings (who can push updates) + * Timing/config changes made through proposals + * Events like `RewardRateUpdated` + +
+ +
+ +Auto Delegate Strategy + +* **Address:** [`0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158`](https://etherscan.io/address/0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158) +* **Purpose:** Implements the “Overwhelming Support” auto-delegation strategy. This contract casts votes on behalf of un-delegated or transferred stOBOL when proposals receive strong community support. This mechanism uses tokens that would otherwise not be available in governance to ensure uncontroversial proposals will meet quorum. +* **What you can find onchain:** + * Parameters like `supportThreshold`, `subQuorumBips`, and `votingWindow` + * Proposals voted on by the strategy + * Vote power amounts cast + * Event logs showing execution activity + * Wallets or protocols interacting with auto-delegation logic + +
+ +## Learn more about... + +[token-utility.md](token-utility.md) +[staking-and-stobol.md](staking-and-stobol.md) +[token-distribution-and-liquidity.md](token-distribution-and-liquidity.md) +[token-holders-faq.md](token-holders-faq.md) +[tge-faq.md](tge-faq.md) diff --git a/versioned_docs/version-v1.5/community-and-governance/obol-token/staking-and-stobol.md b/versioned_docs/version-v1.5/community-and-governance/obol-token/staking-and-stobol.md new file mode 100644 index 0000000000..6fad699077 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/obol-token/staking-and-stobol.md @@ -0,0 +1,78 @@ +--- +description: "This page explains how OBOL staking works, the role of stOBOL, and what happens when tokens are delegated, transferred, or used in DeFi protocols. You can stake and unstake OBOL via stake.obol.org." +sidebar_label: "Staking & stOBOL" +slug: /community-and-governance/obol-token/staking-and-stobol +--- + +# Staking & stOBOL + +## Overview + +Staking allows OBOL token holders to participate in governance while earning rewards. When you stake OBOL, you receive a liquid staking token called stOBOL. This token is transferable, composable in DeFi, and earns staking rewards while maintaining governance power, as long as it remains in the same address that originally staked the OBOL Tokens. It represents a flexible and powerful tool to both support the network and engage in the broader ecosystem. + +stOBOL unlocks new opportunities for participation. It is yield-bearing, enables seamless governance engagement, and is expected to be increasingly integrated across DeFi platforms. If it is transferred elsewhere, direct delegation is removed and governance power is reassigned an Auto-Delegate, preventing governance attacks. The voting behaviour of the Auto-Delegate is determined by the active strategy. + +### To Recap + +* stOBOL is a liquid staking token received when you stake OBOL. +* It allows users to earn staking rewards which auto-compound while retaining governance power. +* stOBOL is fully transferable (ERC-20) and can be used in DeFi (e.g., as collateral). + +## Key Concepts + +
FeatureOBOLstOBOL
Governance voting✅ (direct or delegated)✅ (only if kept on original staking address, otherwise governance power reallocated to the Auto-Delegate)
Transferable
Used in DeFi✅ (less efficient, not yield-bearing)✅ (yield-bearing)
Earns staking rewards
+ +## Delegation & Governance + +Governance power is fundamentally tied to the OBOL Token. When OBOL is staked, the governance power does not transfer to stOBOL itself but remains associated with the underlying staked OBOL. stOBOL serves as a representation of that staked position, surfacing its governance power **only while being held in the same address** that originally staked the OBOL. + +If stOBOL is transferred to another address or smart contract, governance power is not automatically preserved. Instead: + +* By default, the governance power is reassigned to the **Auto-Delegate**. +* However, the receiving address or smart contract **can explicitly delegate** the voting power of its stOBOL to a delegate of choice, if such functionality is supported. + +This design ensures that governance power follows clear, transparent rules: + +* **No double-counting**: the OBOL held in the staking contract is not counted separately from the stOBOL in circulation. +* **No governance arbitrage**: someone cannot gain voting rights simply by borrowing or acquiring stOBOL without also controlling the original staking delegation. + +If stOBOL is used in DeFi protocols (e.g., as collateral on Morpho), governance power defaults to the Auto-Delegate unless the protocol itself implements explicit delegation support for pooled stOBOL assets. + +## How the Auto-Delegate Strategy Works (Current: Overwhelming Support) + +When a liquid staking token (like stOBOL) is transferred, any previous delegation is removed. To prevent this from harming quorum or enabling governance attacks, the system can route that voting power through the Auto-Delegate strategy. The first strategy implemented is called the "Overwhelming Support". This fallback strategy only casts votes using its accrued governance power **in favor** of a proposal when all the following conditions are met: + +* **Sub-quorum reached:** At least 66% of the quorum is already met by FOR votes (`subQuorumBips = 66%`). +* **High support threshold:** At least 90% of votes cast so far are FOR votes (`supportThreshold = 90%`). +* **Within final voting window:** The proposal is within \~2.5 days of its deadline (`votingWindow = 14400` blocks). + +If all three criteria are met, the strategy casts its voting power FOR the proposal. If not, it abstains. + +This ensures that fallback voting power (from transferred stOBOL) is only used to support proposals that already have overwhelming community backing. It avoids influencing contentious or split decisions, protecting governance neutrality and reducing capture risk. + +This model preserves network governance while allowing for stOBOL to flow through DeFi protocols. + +Other strategies can be proposed via governance. + +## Summary Flow + +1. OBOL is staked and stOBOL is minted to the staker’s address. +2. While stOBOL remains with the same address, governance power is retained and delegated as usual. +3. If stOBOL is transferred, governance power is removed and reassigned via the current Auto-Delegate strategy (Overwhelming Support). Other strategies can be proposed via governance. + +![](/img/gitbook/stOBOL_03-3.png) + +## Additional Notes + +* You can stake and unstake OBOL via [stake.obol.org](https://vote.obol.org/stake). +* Voting and delegation are managed at [vote.obol.org](https://vote.obol.org/). + +The Auto-Delegate and underlying strategies are modular and designed to evolve. It represents an initial approach to handling undelegated voting power, but additional strategies can be proposed by the Collective over time. As the Collective matures, we expect to iterate and improve on these mechanisms together. + +As the protocol evolves, new strategies or staking configurations may be introduced through Collective governance. Feedback from the community helps inform these decisions. + +Have questions? Join our [Discord](https://discord.gg/n6ebKsX46w) or visit the [Governance Forum](https://community.obol.org). + +*** + +_This page will evolve as more staking strategies and integrations are launched._ diff --git a/versioned_docs/version-v1.5/community-and-governance/obol-token/tge-faq.md b/versioned_docs/version-v1.5/community-and-governance/obol-token/tge-faq.md new file mode 100644 index 0000000000..2d2e3766a6 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/obol-token/tge-faq.md @@ -0,0 +1,170 @@ +--- +sidebar_label: "TGE FAQ" +slug: /community-and-governance/obol-token/tge-faq +--- + +# TGE FAQ + +## Unlock and Listing + +
+ +How do I unlock my OBOL Tokens received in the Airdrop? + +Starting May 7th at 11:00 AM UTC, visit [**claim.obol.org**](https://claim.obol.org), click **“Unlock”**, and follow the steps. + +
+ +
+ +When is the official TGE date and time? + +The OBOL Token will be listed on exchanges for deposit, trading and withdrawals on May 7th, 2025 at 11:00 AM UTC + +
+ +
+ +Where will the OBOL Token be listed for trading? + +* **Binance**, **Bybit**, **Bitget**, **Gate.io**, **MEXC**, and others. + +- Check [CoinGecko](https://coingecko.com) or [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) for the most up-to-date list. + +
+ +
+ +What are the exact listing times on exchanges? + +* **Binance Alpha** – _May 7 at 10:00 AM UTC_ + +- **Binance Futures** – _May 7 at 10:30 AM UTC_ + +* **Bybit, Gate.io, Bitget, MEXC** – _May 7 at 11:00 AM UTC_ + +
+ +
+ +Where can I track the price of the OBOL Token? + +[CoinGecko](https://coingecko.com) and [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) + +
+ +
+ +Where can I buy the OBOL Token onchain? + +* A **Uniswap v3 pool** will be seeded with initial liquidity. + +- The contract address is [here](https://etherscan.io/address/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434). + +* Anyone can start a pool. Check live prices via **CoinGecko**, or **CoinMarketCap**. + +
+ +
+ +Are there any country restrictions for claiming or trading the OBOL Token? + +* Yes. Each venue has its own restrictions. + +- Unlocking OBOL Tokens received through the Airdrop is subject to the same geo restrictions as claiming. + +
+ +## **Token Supply & Distribution** + +
+ +What is the circulating supply at TGE? + +Approximately 19**%**. Full breakdown is on [CoinMarketCap](https://coinmarketcap.com/currencies/obol/). + +
+ +
+ +Why does Etherscan show 374M tokens instead of 500M? + +For legal and tax reasons, not all tokens are minted yet. + +
+ +
+ +How many tokens were allocated to CoinList, and how many unlock at TGE? + +Details available on the [**Coinlist Sale Page**](https://coinlist.co/obol). + +
+ +
+ +When were unclaimed airdrop tokens returned to the treasury? + +As approved by [**OIP-2**](https://community.obol.org/t/oip-2-unlock-obol-token/317), they were [returned](https://etherscan.io/tx/0x738b4c252bb4613b9945e3b6426ec4ee510c6cdb86027fe20d533c4799a3a331) on **May 2, 2025**. + +
+ +## **Unlocks & Vesting** + +
+ +Can CoinList participants claim at TGE? + +Yes, a portion of their tokens will unlock on May 7th at 11AM UTC per the [**Coinlist terms**](https://coinlist.co/obol). + +
+ +
+ +Will RAF1 tokens be available at TGE? + +RAF1 tokens will be distributed **shortly after TGE**. + +
+ +
+ +When will OBOL Token incentives be claimable? + +Starting May 12, 2025 + +
+ +## **Token Utility** + +
+ +What is the utility of the OBOL Token? + +See the top of the page + +
+ +
+ +What is stOBOL? + +A staked version of the OBOL Token that can be used in DeFi or with restaking platforms. + +
+ +
+ +Can the OBOL or stOBOL Tokens be used in DeFi? + +Yes. More info will follow **post-TGE**. + +
+ +
+ +Are there incentives for providing DeFi liquidity with OBOL or stOBOL? + +**Not at TGE**, but proposals for incentives can be submitted via governance. + +
diff --git a/versioned_docs/version-v1.5/community-and-governance/obol-token/token-distribution-and-liquidity.md b/versioned_docs/version-v1.5/community-and-governance/obol-token/token-distribution-and-liquidity.md new file mode 100644 index 0000000000..649045f286 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/obol-token/token-distribution-and-liquidity.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Distribution & Liquidity" +slug: /community-and-governance/obol-token/token-distribution-and-liquidity +--- + +# Token Distribution & Liquidity + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](https://docs.obol.org/community-and-governance/governance/raf)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.5/community-and-governance/obol-token/token-holders-faq.md b/versioned_docs/version-v1.5/community-and-governance/obol-token/token-holders-faq.md new file mode 100644 index 0000000000..b4774dd49c --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/obol-token/token-holders-faq.md @@ -0,0 +1,135 @@ +--- +description: "This page is designed to answer the most common questions from OBOL token holders, particularly those holding liquid OBOL or stOBOL." +sidebar_label: "Token Holders FAQ" +slug: /community-and-governance/obol-token/token-holders-faq +--- + +# Token Holders FAQ + +## General + +
+ +What is the OBOL token used for? + +OBOL is the governance token of the Obol Collective. It enables holders to participate in on-chain governance by voting directly or delegating their voting power to delegates. + +OBOL is also used in the [RAF](../governance/raf/), where token holders delegate to vote on which contributors should receive retroactive funding for valuable work. + +In addition, OBOL can be staked to receive stOBOL, a liquid token that accrues staking rewards and retains governance power as long as it remains in the staker’s wallet. This staking mechanism supports long-term alignment and decentralized ownership. + +Finally, both OBOL and stOBOL are being integrated into DeFi protocols, such as liquidity pools, lending platforms (e.g. Morpho), and restaking services (e.g. Eigenlayer, Symbiotic), with more utility expected over time as shaped by community governance. + +
+ +
+ +What is stOBOL? + +stOBOL is the liquid staking token received when you stake OBOL. It earns staking rewards and can be used in DeFi. Holding stOBOL in your wallet preserves your governance power. More info in [staking-and-stobol.md](staking-and-stobol.md "mention") + +
+ +
+ +Where can I see OBOL price, supply, and markets? + +You can track OBOL on [CoinMarketCap](https://www.coingecko.com/en/coins/obol-2) or [Coingecko](https://coingecko.com). These pages include market data, supply information, and live price charts. + +
+ +## Delegation & Governance + +
+ +How do I delegate my OBOL tokens? + +You can delegate via [vote.obol.org](https://vote.obol.org/dao/delegates). Connect your wallet, choose a delegate, and confirm the delegation transaction. + +
+ +
+ +What happens if I stake OBOL? + +You receive stOBOL, which maintains your delegation as long as it stays in your wallet. Once transferred (e.g., to a DeFi protocol), you lose the individual delegation. Voting power is then routed via an [auto-delegation strategy](staking-and-stobol.md#how-the-auto-delegate-strategy-works-current-overwhelming-support). + +
+ +
+ +Can I change my delegate? + +Yes, you can re-delegate at any time through the Collective Portal at [vote.obol.org](https://vote.obol.org) + +
+ +
+ +Does holding OBOL give me passive income? + +Not directly. Only staking OBOL (to receive auto-compounding stOBOL) allows you to earn rewards. + +
+ +## Staking & stOBOL + +
+ +How do I stake OBOL? + +Use [stake.obol.org](https://stake.obol.org) to stake. You’ll receive auto-compounding stOBOL in return. + +
+ +
+ +Can I transfer stOBOL? + +Yes, stOBOL is a fully transferable ERC-20 token. However, if you transfer it, your direct delegation is lost, and your governance power enters the auto-delegation pool. + +
+ +
+ +Where can I use stOBOL? + +stOBOL can be used in DeFi protocols (e.g., as collateral, in LPs, etc.). Integrations are ongoing and will be announced via Discord and Twitter. + +
+ +
+ +Can I unstake OBOL? + +Yes. You can return stOBOL to the staking contract at anytime without lockup to reclaim your OBOL. Unstaking and restaking interfaces are provided at [stake.obol.org](https://stake.obol.org). + +
+ +## Token Value & Utility + +
+ +What gives the OBOL token value? + +OBOL gains utility through governance rights, staking yield, and its use in DeFi. Long term, its value could be tied to the growth of the Obol Network, including fees, protocol usage, and TVL. + +
+ +
+ +Does OBOL accrue fees? + +Currently, OBOL does not accrue protocol revenue. However, the DAO may vote in the future to direct protocol revenue toward token holders or stakers. + +
+ +
+ +How can I stay up to date on OBOL news? + +Join our [Discord](https://discord.gg/obol), follow [@ObolNetwork](https://x.com/Obol_Collective), and check our [Forum](https://community.obol.org) for governance and integration updates. + +
+ +_This page is updated regularly. If your question isn’t listed, reach out via Discord or the Governance Forum._ diff --git a/versioned_docs/version-v1.5/community-and-governance/obol-token/token-utility.md b/versioned_docs/version-v1.5/community-and-governance/obol-token/token-utility.md new file mode 100644 index 0000000000..6adaca1495 --- /dev/null +++ b/versioned_docs/version-v1.5/community-and-governance/obol-token/token-utility.md @@ -0,0 +1,44 @@ +--- +sidebar_label: "Token Utility" +slug: /community-and-governance/obol-token/token-utility +--- + +# Token Utility + +## **Governance** + +OBOL Token holders delegate their voting power to delegates who participate in the Token House decision-making processes. This includes voting on proposals affecting the Obol Collective’s direction, upgrades, and funding allocations. Read more about the Token House [here](../governance/token-house.md). + +## **Obol Retroactive Funding (RAF)** + +Token holders delegate their voting power to Delegates, who vote on the projects eligible for retroactive funding. Read more about the Obol RAF [here](../governance/raf/). + +## **OBOL Token Staking** + +As per[ OIP-1](https://community.obol.org/t/oip-1-building-and-enabling-staking-for-the-obol-token/312), OBOL token holders will have the opportunity to stake their tokens, contributing to the security and stability of the Collective by preserving governance while earning rewards and being able to engage in DeFi. Staking involves depositing OBOL tokens in a vault (without lockup) that automatically delegates the Tokens if not done already. In return, stakers receive stOBOL, which automatically accrues OBOL Tokens as rewards as it's price vs OBOL increases. + +This staking program will be implemented in phases, allowing the community to gradually engage in and benefit from the system while reinforcing the decentralization of the Obol Collective. For the first six months, the total rewards will be 0.33% of the total supply, providing early participants with attractive rewards. After this period, the staking rewards may be adjusted based on governance proposals and market conditions. This structured rollout ensures a sustainable and rewarding staking experience while reinforcing the decentralization of the Obol Collective. + +To get started, simply visit [https://stake.obol.org](https://stake.obol.org) and follow the staking flow — no technical setup required. The interface will guide you through selecting your wallet, choosing the amount to stake, and submitting the transaction. + +**You will find more info about the OBOL token staking in the dedicated** [staking-and-stobol.md](staking-and-stobol.md "mention") **section.** + +## **DeFi** + +Plans are in place to launch several DeFi avenues for the OBOL Token post-TGE, such as liquidity pools, lending protocols (e.g. Morpho) and restaking (e.g. Eigenlayer, Symbiotic). + +### Pendle Integration for stOBOL + +_Note: The Pendle integration is not yet live. It is expected to go live in the first half of August 2025. This information is provided in advance for community awareness._ + +stOBOL is supported on [Pendle Finance](https://app.pendle.finance), enabling users to access advanced yield strategies with their staked OBOL. + +Through Pendle, users can isolate and trade the future yield of stOBOL by buying or selling its **Principal Tokens (PT)** and **Yield Tokens (YT)**. + +This opens up new opportunities: holders can lock in fixed yield by purchasing PTs, speculate on rising yield by acquiring YTs, or passively earn through **liquidity provision**, which offers exposure to swap fees and additional PENDLE incentives. Importantly, Pendle pools are **permissionless**, and while the Obol Association has provided initial liquidity to bootstrap the market, anyone can contribute. \ +\ +For more details, refer to the [Pendle Academy](https://pendle.gitbook.io/pendle-academy) and [stOBOL pool on Pendle](https://app.pendle.finance/trade). + +## **More Utility Coming Soon** + +Via Token House governance proposals in the [Governance Forum](https://community.obol.org/), the Obol community can add more functionality and utility to the OBOL Token. diff --git a/versioned_docs/version-v1.5/learn/charon/README.md b/versioned_docs/version-v1.5/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.5/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.5/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.5/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..39b50bb526 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/charon/charon-cli-reference.md @@ -0,0 +1,751 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.5.2`](https://github.com/ObolNetwork/charon/releases/tag/v1.5.2). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. + --zipped Create a tar archive compressed with gzip of the cluster directory after creation. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost (default "default") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH+ staked for each). (default 1) + --operator-addresses strings Comma-separated list of each operator's Ethereum address. + --operator-enrs strings Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + --publish Creates an invitation to the DKG ceremony on the DV Launchpad. Terms and conditions apply. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 30s) + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 1m0s) +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --consensus-protocol string Preferred consensus protocol name for the node. Selected automatically when not specified. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + --graffiti strings Comma-separated list or single graffiti string to include in block proposals. List maps to validator's public key in cluster lock. Appends "OB" suffix to graffiti. Maximum 28 bytes per graffiti. + --graffiti-disable-client-append Disables appending "OB" suffix to graffiti. Increases maximum bytes per graffiti to 32. + -h, --help Help for run + --jaeger-address string [DISABLED] Listening address for jaeger tracing. + --jaeger-service string [DISABLED] Service name used for jaeger tracing. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --otlp-address string Listening address for OTLP gRPC tracing backend. + --otlp-service-name string Service name used for OTLP gRPC tracing. (default "charon") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") + --vc-tls-cert-file string The path to the TLS certificate file used by charon for the validator client API endpoint. + --vc-tls-key-file string The path to the TLS private key file associated with the provided TLS certificate. +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its validator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default ".charon/cluster") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Test subcommands provide test suite to evaluate current cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad DirectConn Libp2pTCPPortOpen PingRelay PingMeasureRelay PeerCount PingLoad Simulate1 Simulate100 Simulate500 Ping Simulate10 Simulate1000 SimulateCustom PingMeasure Version Synced Ping PingMeasure PingLoad CreateBlock Ping PingMeasure TotalMemory InternetDownloadSpeed DiskReadSpeed InternetLatency InternetUploadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadIOPS AvailableMemory] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PeerCount Simulate100 Simulate500 Simulate1000 SimulateCustom Version Synced PingLoad Simulate1 Simulate10] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [DiskWriteSpeed DiskWriteIOPS AvailableMemory TotalMemory InternetDownloadSpeed InternetUploadSpeed DiskReadSpeed DiskReadIOPS InternetLatency] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure CreateBlock] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [DirectConn Ping PingMeasure PingLoad Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.5/learn/charon/charon-networking.md b/versioned_docs/version-v1.5/learn/charon/charon-networking.md new file mode 100644 index 0000000000..acf16157fe --- /dev/null +++ b/versioned_docs/version-v1.5/learn/charon/charon-networking.md @@ -0,0 +1,83 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview[​](https://docs.obol.org/learn/charon/networking#overview) {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](https://docs.obol.org/learn/charon/networking#internal-validator-stack) and the [_external p2p network_](https://docs.obol.org/learn/charon/networking#external-p2p-network). + +### Internal Validator Stack[​](https://docs.obol.org/learn/charon/networking#internal-validator-stack) {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network[​](https://docs.obol.org/learn/charon/networking#external-p2p-network) {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](https://docs.obol.org/learn/charon/charon-cli-reference): + +* `--p2p-tcp-addresses`: Addresses for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security[​](https://docs.obol.org/learn/charon/networking#libp2p-authentication-and-security) {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](https://docs.obol.org/learn/charon/cluster-configuration#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p’s Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery[​](https://docs.obol.org/learn/charon/networking#libp2p-relays-and-peer-discovery) {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\ + + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters[​](https://docs.obol.org/learn/charon/networking#scalable-relay-clusters) {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URls. diff --git a/versioned_docs/version-v1.5/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.5/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..babea8e6e0 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralized backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long term decentralization of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definiition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.5/learn/charon/dkg.md b/versioned_docs/version-v1.5/learn/charon/dkg.md new file mode 100644 index 0000000000..6024f9a93e --- /dev/null +++ b/versioned_docs/version-v1.5/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENRs nonce and resign with the clients private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participants old keys out of a distributed validator in favor of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.5/learn/charon/intro.md b/versioned_docs/version-v1.5/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.5/learn/further-reading/README.md b/versioned_docs/version-v1.5/learn/further-reading/README.md new file mode 100644 index 0000000000..6f13128d79 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/further-reading/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading + diff --git a/versioned_docs/version-v1.5/learn/further-reading/community-testing.md b/versioned_docs/version-v1.5/learn/further-reading/community-testing.md new file mode 100644 index 0000000000..91ebf1cfde --- /dev/null +++ b/versioned_docs/version-v1.5/learn/further-reading/community-testing.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community Testing" +slug: /learn/further-reading/community-testing +--- + +# Community Testing + diff --git a/versioned_docs/version-v1.5/learn/further-reading/ethereum-and-its-relationship-with-dvt.md b/versioned_docs/version-v1.5/learn/further-reading/ethereum-and-its-relationship-with-dvt.md new file mode 100644 index 0000000000..52001d8401 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/further-reading/ethereum-and-its-relationship-with-dvt.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum-and-its-relationship-with-dvt +--- + +# Ethereum and Its Relationship With DVT + diff --git a/versioned_docs/version-v1.5/learn/further-reading/peer-score.md b/versioned_docs/version-v1.5/learn/further-reading/peer-score.md new file mode 100644 index 0000000000..7d232ebfa1 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/further-reading/peer-score.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer-score +--- + +# Peer Score + diff --git a/versioned_docs/version-v1.5/learn/further-reading/useful-links.md b/versioned_docs/version-v1.5/learn/further-reading/useful-links.md new file mode 100644 index 0000000000..627e249966 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/further-reading/useful-links.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Useful Links" +slug: /learn/further-reading/useful-links +--- + +# Useful Links + diff --git a/versioned_docs/version-v1.5/learn/futher-reading/README.md b/versioned_docs/version-v1.5/learn/futher-reading/README.md new file mode 100644 index 0000000000..445121c906 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/futher-reading/README.md @@ -0,0 +1,8 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/futher-reading/futher-reading +unlisted: true +--- + +# Further Reading + diff --git a/versioned_docs/version-v1.5/learn/futher-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.5/learn/futher-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..577e2b0347 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/futher-reading/ethereum_and_dvt.md @@ -0,0 +1,56 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/futher-reading/ethereum_and_dvt +unlisted: true +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.5/learn/futher-reading/peer_score.md b/versioned_docs/version-v1.5/learn/futher-reading/peer_score.md new file mode 100644 index 0000000000..2acfe3c1cc --- /dev/null +++ b/versioned_docs/version-v1.5/learn/futher-reading/peer_score.md @@ -0,0 +1,49 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/futher-reading/peer_score +unlisted: true +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of the ethereum network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.5/learn/futher-reading/resources.md b/versioned_docs/version-v1.5/learn/futher-reading/resources.md new file mode 100644 index 0000000000..0a9b60f1c8 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/futher-reading/resources.md @@ -0,0 +1,60 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/futher-reading/resources +unlisted: true +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.5/learn/futher-reading/testnet.md b/versioned_docs/version-v1.5/learn/futher-reading/testnet.md new file mode 100644 index 0000000000..9244762697 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/futher-reading/testnet.md @@ -0,0 +1,191 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/futher-reading/testnet +unlisted: true +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.5/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.5/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..2a5ef8cad6 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/readme/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General[​](https://docs.obol.org/learn/intro/faq#general) {#general} +#### Does Obol have a token?[​](https://docs.obol.org/learn/intro/faq#does-obol-have-a-token) {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/obol-token/) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is 0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7. + +#### Where can I learn more about Distributed Validators?[​](https://docs.obol.org/learn/intro/faq#where-can-i-learn-more-about-distributed-validators) {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from?[​](https://docs.obol.org/learn/intro/faq#where-does-the-name-charon-come-from) {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node?[​](https://docs.obol.org/learn/intro/faq#what-are-the-hardware-requirements-for-running-a-charon-node) {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster?[​](https://docs.obol.org/learn/intro/faq#what-is-the-difference-between-a-node-a-validator-and-a-cluster) {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine?[​](https://docs.obol.org/learn/intro/faq#can-i-migrate-an-existing-charon-node-to-a-new-machine) {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation[​](https://docs.obol.org/learn/intro/faq#distributed-key-generation) {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator?[​](https://docs.obol.org/learn/intro/faq#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator) {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum numbers of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-threshold). + +### Obol Splits[​](https://docs.obol.org/learn/intro/faq#obol-splits) {#obol-splits} +#### What are Obol Splits?[​](https://docs.obol.org/learn/intro/faq#what-are-obol-splits) {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in future a number of other LSPs. + +#### Are Obol Splits non-custodial?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-non-custodial) {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split?[​](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split) {#can-i-change-the-percentages-in-a-split} +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work?[​](https://docs.obol.org/learn/intro/faq#how-do-obol-splits-work) {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](https://docs.obol.org/learn/intro/obol-splits). + +#### Are Obol Splits open source?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-open-source) {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-audited) {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](https://docs.obol.org/adv/security/smart_contract_audit). + +#### Are the Obol Splits contracts verified on Etherscan?[​](https://docs.obol.org/learn/intro/faq#are-the-obol-splits-contracts-verified-on-etherscan) {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts?[​](https://docs.obol.org/learn/intro/faq#does-my-cold-wallet-have-to-call-the-obol-splits-contracts) {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits?[​](https://docs.obol.org/learn/intro/faq#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits) {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst case mass slashing on the network. Consult the documentation on the contract [here](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient), its audit [here](https://docs.obol.org/adv/security/smart_contract_audit), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs[​](https://docs.obol.org/learn/intro/faq#debugging-errors-in-logs) {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](https://docs.obol.org/adv/troubleshooting/errors). diff --git a/versioned_docs/version-v1.5/learn/intro/key-concepts.md b/versioned_docs/version-v1.5/learn/intro/key-concepts.md new file mode 100644 index 0000000000..6ff0d5b5d4 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/key-concepts.md @@ -0,0 +1,112 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/readme/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimizing downtime in mission critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specializes in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof of stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys, that together operate as a threshold key for participating in proof of stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that needs to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 4 | 3/4 | Minimum threshold | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.5/learn/intro/launchpad.md b/versioned_docs/version-v1.5/learn/intro/launchpad.md new file mode 100644 index 0000000000..6b590f8ec7 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/launchpad.md @@ -0,0 +1,52 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/readme/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~** Staking Launchpad**](https://launchpad.ethereum.org/), a public good open source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +|------------------|----------------------------------------| +| Mainnet | https://launchpad.obol.org | +| Gnosis Chain | https://gnosischain.launchpad.obol.org | +| Hoodi | https://hoodi.launchpad.obol.org | +| Holesky | https://holesky.launchpad.obol.org | +| Sepolia | https://sepolia.launchpad.obol.org | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +> [!TIP] +> If you created a cluster locally, and didn't use the `--publish` command at the time, you can manually publish it by running this command from the folder with the `cluster-lock.json` in it. +> +> `curl -X POST -H "Content-Type: application/json" -d @cluster-lock.json https://api.obol.tech/v1/lock` + +## Use the Explorer + +Clicking "explore" on the top right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.5/learn/intro/obol-collective.md b/versioned_docs/version-v1.5/learn/intro/obol-collective.md new file mode 100644 index 0000000000..c9d159635b --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/readme/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +The Obol Collective is the largest Decentralized Operator Ecosystem. We provides the technology, opportunities, and community to scale decentralized infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../futher-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](https://docs.obol.org/api), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.5/learn/intro/obol-incentives.md b/versioned_docs/version-v1.5/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..204b5546e0 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/obol-incentives.md @@ -0,0 +1,181 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/readme/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible shortly after the OBOL Token is unlocked (as per O[IP#2](https://community.obol.org/t/oip-2-unlock-obol-token/)) and starts trading. + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + + + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at anytime but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.gg/obol](https://discord.gg/obol). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | + diff --git a/versioned_docs/version-v1.5/learn/intro/obol-splits.md b/versioned_docs/version-v1.5/learn/intro/obol-splits.md new file mode 100644 index 0000000000..d7e58ff3df --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/obol-splits.md @@ -0,0 +1,122 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/readme/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators and their surrounding ecosystem of decentralised infrastructure. These contracts include: + +* Reward Splitting contracts: Contracts to split ether (and tokens) across multiple entities. Developed by [Splits.org](https://splits.org/) + +Key Design Principles the Obol Smart Contract suite include are: + +- That they are secure. All [released](https://github.com/ObolNetwork/obol-splits/releases/) Obol Splits products are [audited by high quality security teams](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments). +- They are not upgradeable. +- They are self-soverign. Any permissioned actions, such as withdrawal, exit, or operator rotation, are controlled by the user, not an unaccountable set of third parties with the ability to upgrade your contracts behaviour. +- They do not require a token to function. +- They are oracle-free. (Unless you intend to leverage a [swapper](https://docs.splits.org/core/swapper)). +- They divide the reward ether from principal ether such that staking providers can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal and reward_. +- That rewards can be withdrawn in an ongoing manner without exiting the validator. (Some conditions apply). + +## Optimistic Withdrawal Recipient[​](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient) {#optimistic-withdrawal-recipient} +![](/img/gitbook/image-15-1-1.png) + +Optimistic Withdrawal Recipients (OWRs) **are the predecessor to Obol Validator Managers**. The primary addition with Validator Managers is the role-based control over validator withdrawals, exits and consolidations. + +Optimistic Withdrawal Recipients allow for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use an splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + + + +## Split Contracts[​](https://docs.obol.org/learn/intro/obol-splits#split-contracts) {#split-contracts} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Validator Managers focus on the former, split contracts focus on the latter. They are best used in tandem. + +![Obol Validator Manager in Tandem with an Execution Layer Fee recipient splitter contract](/img/gitbook/ovm_splits_overview.png) + +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers[​](https://docs.obol.org/learn/intro/obol-splits#split-controllers) {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. We recommend using a [SAFE wallet](https://safe.global) to manage the Split. + +#### (Gnosis) SAFE wallet[​](https://docs.obol.org/learn/intro/obol-splits#gnosis-safe-wallet) {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administrate an editable split. The most well-known deployment of this pattern is the [protocol guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + + +## Deployments + +### Obol Lido Split Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#ols-factory-deployment) + +The `ObolLidoSplit` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/lido/ObolLidoSplitFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [](https://etherscan.io/address/) | +| Hoodi | [0xb633CD420aF83E8A5172e299104842b63dd97ab7](https://hoodi.etherscan.io/address/0xb633CD420aF83E8A5172e299104842b63dd97ab7) | +| Holesky | [](https://holesky.etherscan.io/address/) | +| Sepolia | [](https://sepolia.etherscan.io/address/) | + + +### OWR Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#owr-factory-deployment) + +The `OptimisticWithdrawalRecipient` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Holesky | [0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df](https://holesky.etherscan.io/address/0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | +| Hoodi | [0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7](https://hoodi.etherscan.io/address/0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7) | + +## FAQ + +### What are Obol Splits? + +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido with Obol Lido Splits, and Native Staking with Obol Validator Managers. + +### Are Obol Splits non-custodial? + +Yes. Unless you were to decide to [deploy an editable splitter contract](#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. Obol Validator Managers have owners and Role Based Access Control, but these are self-sovereign and up to the deployer to set and manage. There is no third party with access to or control of your validator unless you grant them such access. + +### Can I change the percentages in a split? + +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a *controllable* splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html#). + +### Are Obol Splits open source? + +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +### Are Obol Splits audited? + +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments) and always deploy contracts only from published [releases](https://github.com/ObolNetwork/obol-splits/releases). + +### Are the Obol Splits contracts verified on Etherscan? + +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +### Does my cold wallet have to call the Obol Splits contracts? + +No. Any address can trigger the contracts to distribute the withdrawn/skimmed ether, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +### Are there any edge cases I should be aware of when using Obol Splits? + +The most important thing to be aware of is what address is the owner of the Obol Validator Manager, whether it has assigned any other addresses any roles, and whether or not the Split contract you are using has been set up with editability and by which address. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is to use a high threshold multi-sign like a SAFE as the `owner`/`controller`, or to renounce ownership and control entirely, and if in future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst case mass slashing on the network. Consult the documentation on the contract [here](../../learn/intro/obol-splits.md#optimistic-withdrawal-recipient), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. diff --git a/versioned_docs/version-v1.5/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.5/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..becb3a6d90 --- /dev/null +++ b/versioned_docs/version-v1.5/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/readme/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and PKI + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.5/run-a-dv/integrations/README.md b/versioned_docs/version-v1.5/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..77e5bf9a25 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# integrations + diff --git a/versioned_docs/version-v1.5/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.5/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..b7b9b507a4 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,58 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) and other applications. + +### Pre-requisites[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#pre-requisites) {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](https://docs.obol.org/next/adv/advanced/quickstart-sdk) is required. + +### Create a SAFE to own the EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-safe-to-own-the-eigenpod) {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-an-eigenpod) {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-splitter-for-the-block-reward) {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-the-dv-cluster-invite) {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](https://docs.obol.org/next/run/start/quickstart_group) on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](https://docs.obol.org/next/run/integrations/quickstart-sdk) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#deposit-and-restake-your-distributed-validator) {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. + diff --git a/versioned_docs/version-v1.5/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.5/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..6621ad1364 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/integrations/dappnode.md @@ -0,0 +1,30 @@ +--- +sidebar_label: "DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# DappNode + +For setup, see quickstart guide:[​](https://docs.obol.org/next/run/integrations/Dappnode#for-setup-see-quickstart-guide) + +For setup of a DV using Dappnode, see the quickstart guide [Create a DV Alone](https://docs.obol.org/next/run/start/quickstart_alone), and select the appropriate tab for "Dappnode". + +### Frequently asked questions[​](https://docs.obol.org/next/run/integrations/Dappnode#frequently-asked-questions) {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster?[​](https://docs.obol.org/next/run/integrations/Dappnode#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-the-validator-and-charon-volumes-to-use-the-same-enr-for-another-cluster) {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC?[​](https://docs.obol.org/next/run/integrations/Dappnode#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag-for-lodestar-vc) {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically.\ + + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol?[​](https://docs.obol.org/next/run/integrations/Dappnode#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-same-dappnode-machine-push-monitoring-data-from-both-clusters-to-obol) {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.5/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.5/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..38c799137f --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,225 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://operatorportal.lido.fi/modules/community-staking-module) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from Holesky just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using CSM UI in advanced mode, using the `extendedManagerPermissions` to set the `managerAddress` to the cluster multi-sig (SAFE) and the `rewardAddress` to the Splits.org splitting contract. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (if members want to use a distinct address to the one they sign with for receiving rewards). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (reccommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol protocol development, thereby earning [Obol Incentives](https://obol.org/incentives) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [protocoldevelopmentfee.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol protocol development. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated a CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create up to 12 validator keys (CSM's Early Access limit) with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create. +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using you favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM is launching with a whitelisted set of approved operators (Early Access). The squad member with EA should be the one to create the node through the CSM widget. + +The EA member will head to [CSM Extended Mode](https://csm.lido.fi/?mode=extended) and connect their wallet. (Note the `mode=extended` parameter.) This allows the Lido CSM reward address to be set to the split contract created earlier. + +![](/img/gitbook/image-47.png) + +The EA member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The EA member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The EA member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button.\\ + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.5/run-a-dv/prepare/README.md b/versioned_docs/version-v1.5/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..6d77f77e82 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# prepare + diff --git a/versioned_docs/version-v1.5/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.5/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..09f03f65be --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,99 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10mb/s internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25mb/s internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimize both performance and cost-effectiveness, it is recommended to prioritize physical over virtualized setups. Such configurations typically offer greater performance and minimize overhead associated with virtualization, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimize Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimize potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes would potentially impact the fault tolerance of the cluster and as a result should be avoided. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. Be sure to use encrypted communication between your VC and the Charon client, potentially through a cloud-provided network, a self-managed network tunnel, a VPN, a Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), or other manner. + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration/#cluster-size-and-resilience)). + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](./test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +The clusters should consist of a combination of your preferred consensus, execution, and validator clients. It is recommended to include a combination of multiple clients in order to have a healthy client diversity within the cluster, ideally, if any single client type fails, it should be less than the fault tolerance of the cluster, and the validators should stay online/not do anything slashable. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Metrics Monitoring + +As requested by Obol Labs, node operators can push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. Our recommendation for operators is to independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (usually < 24 hours). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.5/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.5/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..6988ffd3b2 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatability information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.5/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.5/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..31574b3723 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,554 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + + +:::tip + +Adding the `--publish` flag to the below commands, and running the command from the directory containing your `.charon` folder, will submit the test results to the [Obol API](../../api/what-is-this-api.md). Publishing your performance reports grows the staking node dataset, and allows Obol and Ethereum development teams to make data-driven choices regarding the required specs for validating Ethereum. We hope you will consider opting in. + +::: + + + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + + +:::info + +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the `beacon` node and `validator` client tests, you need to point them toward the correct Docker container, this includes specifying the Docker container’s network. Check your docker networks with the command `docker network ls`. When you run the test command, specify the Docker network with `--network `. + +Read more about docker networking [here](https://docs.docker.com/engine/network/). + +::: + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are easened. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.5.2 alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.5.2 alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + + + + +#### Pre-requisites + +The executable storage tests require `fio` to be installed on your host machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +#### Example run + +```sh +charon alpha test infra +``` + + + + + +#### Example run + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.5.2 alpha test infra \ + --disk-io-test-file-dir=/opt/charon/test +``` + + + diff --git a/versioned_docs/version-v1.5/run-a-dv/running/README.md b/versioned_docs/version-v1.5/run-a-dv/running/README.md new file mode 100644 index 0000000000..515e6cbede --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# running + diff --git a/versioned_docs/version-v1.5/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.5/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..3c7cddf6d9 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +Use any of the following tools to deposit. Please use the third-party tools at your own risk and always double check the staking contract address. + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. diff --git a/versioned_docs/version-v1.5/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.5/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..3d4aa06850 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/running/claim-rewards.md @@ -0,0 +1,66 @@ +--- +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +Introduction[​](https://docs.obol.org/next/run/running/claim-rewards#introduction) + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator’s withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +The method for claiming rewards depends on the Cluster's withdrawal configuration, whether it's an [**OWR**](https://docs.obol.org/next/learn/intro/obol-splits#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](https://docs.obol.org/next/learn/intro/obol-splits#exitable-withdrawal-recipient) . The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +\ + + +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](https://docs.obol.org/run/integrations/lido-csm). | + +### Claim Flow[​](https://docs.obol.org/next/run/running/claim-rewards#claim-flow) {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](https://docs.obol.org/next/learn/intro/obol-splits). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +1. All validator rewards are accumulated in the validator's withdrawal address, which is a split wallet. +2. Claims can be triggered in two ways: + 1. **From addresses in the Splitter**: Splitter addresses will see a `Claim All` button. When the first address (e.g., address A) executes `Claim All`, it triggers a multi-call transaction to distribute rewards from all the split wallets associated with a cluster into the Split Main. The Split Main then sends address A’s proportion of the rewards (based on the split configuration at the time of cluster creation). All of this is executed with a single click for the first address. + 2. **From addresses not in the Splitter**: Non-splitter addresses will see a `Distribute All` button instead of `Claim All`. These addresses cannot claim rewards directly but can distribute rewards to the Split Main (subsidizing transaction fees for others). Operators can then claim rewards later by visiting the same cluster details page. +3. Internally, after clicking `Claim All` or `Distribute All`, the split wallet sends the funds to the Split Main contract. +4. The Split Main then sends proportional rewards to **address A**, completing steps 2a, 3, and 4 with a single click. +5. Other addresses (e.g., B, C, D) can later click on `Claim All` to receive their share of the rewards. + +### Launchpad Edge Cases[​](https://docs.obol.org/next/run/running/claim-rewards#launchpad-edge-cases) {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: The `Claimable` column doesn’t match the amount next to the `Claim All` button. {#case-1-the-claimable-column-doesnt-match-the-amount-next-to-the-claim-all-button} +![](/img/gitbook/image-87.png) + +![](/img/gitbook/image-1-1-1-1-1.png) + +In this scenario, someone else (a splitter or non-splitter address) has already distributed rewards to the Split Main (e.g., 0.12 ETH). However, your validators (4 in this case) have earned an additional 0.2 ETH in rewards. Your total effective claimable balance is 0.032 ETH, which you can claim using the `Claim All` button. + +:::info +Your total effective claimable amount will always be displayed next to the `Claim All` button. +::: + +#### Case 2: You don’t see a `Claim All` button but instead see `Distribute All`.[​](https://docs.obol.org/next/run/running/claim-rewards#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all) {#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all} +![](/img/gitbook/image-88.png) + +This happens because the connected address is not listed in the split configuration. You may have used a different operator address from the one in the splitter configuration. You can: + +* Distribute all rewards using the connected address for all operators and claim using your address in the splitter configuration. +* Switch to the splitter address and claim directly. + +Note: It costs the same gas to distribute rewards for one address as it does for all addresses. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows a `Claim All` amount. {#case-3-you-just-created-a-new-cluster-with-no-active-validators-or-rewards-but-it-shows-a-claim-all} +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all `Claim All` buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.5/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.5/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..8b1d75ea57 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,933 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction[​](https://docs.obol.org/next/run/running/quickstart-exit#introduction) {#introduction} +Users looking to exit staking entirely and withdraw their full balance back must sign and broadcast a "voluntary exit" message with validator keys which will start the process of exiting from staking. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proporiton of principal and rewards. + +There are two ways to sign the partial exit and broadcast the full exit. Both the solutions don't require gas. + +1. **Using the Charon’s exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via launchpad and ability to download partial exits and broadcast them later as required. Users don’t have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use launchpad to monitor exit status and will have to use grafana to query the partial exit status. + +:::info +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +As per your preferences, choose the correct combination of - + +1. **Network** : Mainnet or Holesky +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quanity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +#### Step 1: Submit partial exit {#introduction} + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message.\\ + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](https://docs.obol.org/img/PartialExitsStatus.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch[​](https://docs.obol.org/next/run/running/quickstart-exit#exit-epoch-and-withdrawable-epoch) {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.5/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.5/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..df986f4233 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/running/monitoring.md @@ -0,0 +1,90 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/d6qujIJVk/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show following page. Choose Discord in the `Integration` drop down.\ + + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md). + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.5/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.5/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..c33e9bd637 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,124 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimse liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimse liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + diff --git a/versioned_docs/version-v1.5/run-a-dv/start/README.md b/versioned_docs/version-v1.5/run-a-dv/start/README.md new file mode 100644 index 0000000000..f8e137e70b --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# start + diff --git a/versioned_docs/version-v1.5/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.5/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..d9e55f673d --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,215 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](https://docs.obol.org/run/start/quickstart_group) instead for this latter case. +::: + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_alone#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.5.2 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 create cluster \ + --nodes=6 \ + --network=holesky \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](https://docs.obol.org/next/run/start/quickstart_alone#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately.\ +\ +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Holesky testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Setup the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample.holesky .env +``` +::: + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.5/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.5/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..aaeaa6245c --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,600 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_group#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](https://docs.obol.org/next/run/prepare/deployment-best-practices#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](https://docs.obol.org/next/adv/troubleshooting/errors#docker-permission-denied-error) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client**[**​**](https://docs.obol.org/next/run/start/quickstart_group#prepare-an-execution-and-consensus-client) + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package**[**​**](https://docs.obol.org/next/run/start/quickstart_group#install-the-obol-dappnode-package) + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will be see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge**[**​**](http://localhost:3000/run/start/quickstart_group#installing-sedge) + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful**[**​**](http://localhost:3000/run/start/quickstart_group#check-the-install-was-successful) + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +**Collect addresses, configure the cluster, share the invitation** + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + 1. Select the desired amount of validators (32 ETH each) the cluster will run. (Note that the mainnet launchpad is restricted to one validator for now.) + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr) in the "What is your charon client's ENR?" field. + 3. Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. + 4. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions of participating as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +**Join the cluster prepared by the creator** + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address provided to the leader.\\ + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue.\\ + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr).\\ + + ![](/img/gitbook/image-83.png) +6. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +7. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](https://docs.obol.org/next/learn/charon/dkg) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) \\ + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. \\ + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.5.2 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run.\\ + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page.\\ + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +**Create a DV Node Backup** + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present.\\ + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long term. + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose, further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Holesky testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +````sh +# To prepare the node for the Holesky test network +# Copy ".env.sample.holesky", renaming it ".env" +cp .env.sample.holesky .env + + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env + + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```shell + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +```` + +\{% hint style="warning" %\} Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. \{% endhint %\} + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/d6qujIJVk/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). \{% endtab %\} + +\{% tab title="Sedge" %\} To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-generate) + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Holesky network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=holesky --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-import-key) + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ holesky teku +``` + +**Sedge Run**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-run) + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. \{% endtab %\} + +\{% tab title="Ansible" %\} Use an ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. \{% endtab %\} + +\{% tab title="Helm" %\} Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. \{% endtab %\} + +\{% tab title="Kubernetes" %\} Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. \{% endtab %\} \{% endtabs %\} \{% endtab %\} + +\{% tab title="Existing Beacon Node" %\} \{% hint style="warning" %\} Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. \{% endhint %\} + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Copy the `docker-compose.override.yml.sample` file + +``` + +sh +cp -n docker-compose.override.yml.sample docker-compose.override.yml +``` + +2. Uncomment the `profiles: [disable]` section for both `nethermind` and `lighthouse`. The override file should now look like this + +``` +services: + nethermind: + # Disable nethermind + profiles: [disable] + # Bind nethermind internal ports to host ports + #ports: + #- 8545:8545 # JSON-RPC + #- 8551:8551 # AUTH-RPC + #- 6060:6060 # Metrics + lighthouse: + # Disable lighthouse + profiles: [disable] + # Bind lighthouse internal ports to host ports + #ports: + #- 5052:5052 # HTTP + #- 5054:5054 # Metrics +... +``` + +3. Then, uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +4. Restart your docker compose + +```sh +docker compose down +docker compose up -d +``` + +\{% endtab %\} \{% endtabs %\} + +\{% hint style="success" %\} In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is \` + +:3610\`. Read more about Charon's networking [here](https://docs.obol.org/next/learn/charon/networking). + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](https://docs.obol.org/next/run/running/activate-dv) to begin staking. diff --git a/versioned_docs/version-v1.5/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.5/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..8aa5fff0de --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,56 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics to Obol Monitoring" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics to Obol Monitoring + +:::info +This is **optional** and does not confer any special privileges within the Obol Network. +::: + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](http://localhost:3000/run/start/quickstart_overview), and have been provided with **Monitoring Credentials** used to push distributed validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve your Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +#### Update the monitoring token in the `.env` file + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +#### Save the `.env` file and restart Prometheus + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab.\\ + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it.\\ + + ![](/img/gitbook/image-86.png) + + diff --git a/versioned_docs/version-v1.5/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.5/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..be7af33fc1 --- /dev/null +++ b/versioned_docs/version-v1.5/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to utilize Distributed Validators for solo or multi-operator staking. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](./create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](./create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.5/sdk/classes/Client.md b/versioned_docs/version-v1.5/sdk/classes/Client.md new file mode 100644 index 0000000000..a19a70f5e8 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/classes/Client.md @@ -0,0 +1,244 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +### Extends + +* `Base` + +### Constructors + +#### new Client() + +> **new Client**(`config`, `signer`?): [`Client`](Client.md) + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | -------- | --------------------- | +| `config` | `object` | Client configurations | +| `config.baseUrl`? | `string` | obol-api url | +| `config.chainId`? | `number` | Blockchain network ID | +| `signer`? | `Signer` | ethersJS Signer | + +**Returns** + +[`Client`](Client.md) + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client: [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +**Overrides** + +`Base.constructor` + +**Defined in** + +index.ts:66 + +### Methods + +#### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`<`string`> + +Accepts Obol terms and conditions to be able to create or update data. + +**Returns** + +`Promise`<`string`> + +terms and conditions acceptance success message. + +**Throws** + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions: [acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +**Defined in** + +index.ts:79 + +*** + +#### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys OWR and Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| --------------------- | ------------------------------------------------------------- | --------------------------------------- | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit: [createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:133 + +*** + +#### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| ------------------- | ----------------------------------------------------------- | -------------------------------------------------- | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit: [createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:254 + +*** + +#### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`<`string`> + +Creates a cluster definition which contains cluster configuration. + +**Parameters** + +| Parameter | Type | Description | +| ------------ | ----------------------------------------------------- | ----------------------- | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +**Returns** + +`Promise`<`string`> + +config\_hash. + +**Throws** + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition: [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +**Defined in** + +index.ts:350 + +*** + +#### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Approves joining a cluster with specific configuration. + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition. + +**Throws** + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition: [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +**Defined in** + +index.ts:415 + +*** + +#### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | ---------------------------------------------------------- | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition for config hash + +**Throws** + +On not found config hash. + +An example of how to use getClusterDefinition: [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +**Defined in** + +index.ts:469 + +*** + +#### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | -------------------------------------------- | +| `configHash` | `string` | The configuration hash in cluster-definition | + +**Returns** + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +**Throws** + +On not found cluster definition or lock. + +An example of how to use getClusterLock: [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +**Defined in** + +index.ts:488 diff --git a/versioned_docs/version-v1.5/sdk/classes/README.md b/versioned_docs/version-v1.5/sdk/classes/README.md new file mode 100644 index 0000000000..d71a58615e --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# classes + diff --git a/versioned_docs/version-v1.5/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.5/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..7e4d9cb8ef --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,16 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------------------ | -------- | ------------- | ----------- | +| `0x00000000` | `1` | Mainnet | types.ts:6 | +| `0x00001020` | `5` | Goerli/Prater | types.ts:9 | +| `0x00000064` | `100` | Gnosis Chain | types.ts:12 | +| `0x01017000` | `17000` | Holesky | types.ts:15 | +| `0x10000910` | `560048` | Hoodi | types.ts:18 | diff --git a/versioned_docs/version-v1.5/sdk/enumerations/README.md b/versioned_docs/version-v1.5/sdk/enumerations/README.md new file mode 100644 index 0000000000..5069f1f6ed --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# enumerations + diff --git a/versioned_docs/version-v1.5/sdk/functions/README.md b/versioned_docs/version-v1.5/sdk/functions/README.md new file mode 100644 index 0000000000..62be7a3a85 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# functions + diff --git a/versioned_docs/version-v1.5/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.5/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..cb920b4b8b --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/functions/validateClusterLock.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock + +> **validateClusterLock**(`lock`): `Promise`<`boolean`> + +Verifies Cluster Lock's validity. + +### Parameters + +| Parameter | Type | Description | +| --------- | ----------------------------------------------- | ------------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | + +### Returns + +`Promise`<`boolean`> + +boolean result to indicate if lock is valid + +### Throws + +on missing keys or values. + +An example of how to use validateClusterLock: [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) + +### Defined in + +services.ts:13 diff --git a/versioned_docs/version-v1.5/sdk/index.md b/versioned_docs/version-v1.5/sdk/index.md new file mode 100644 index 0000000000..4ac27305d8 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/index.md @@ -0,0 +1,91 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + + + SDK Version: v2.1.0 + + +![Obol Logo](https://obol.org/obolnetwork.png) + +

Obol SDK

+ +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](https://docs.obol.org/api). + +## Getting Started + +Checkout our [docs](https://docs.obol.org/advanced/quickstart-sdk), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +## Terms and Conditions +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +## ⚠️ Important Security Notice: +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +- The private key is securely stored (e.g., in an `.env` file). +- Never commit or push your `.env` file containing the private key to version control. + +## Contributing + +Please review the following guidelines: + +- [How to Report Bugs](#how-to-report-bugs) +- [How to Propose Changes](#how-to-propose-changes) +- [Code Review Process](#code-review-process) + +### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +## Enumerations + +- [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +## Classes + +- [Client](classes/Client.md) + +## Interfaces + +- [ClusterDefinition](interfaces/ClusterDefinition.md) +- [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) + +## Type Aliases + +- [ClusterOperator](type-aliases/ClusterOperator.md) +- [OperatorPayload](type-aliases/OperatorPayload.md) +- [ClusterCreator](type-aliases/ClusterCreator.md) +- [ClusterValidator](type-aliases/ClusterValidator.md) +- [ClusterPayload](type-aliases/ClusterPayload.md) +- [SplitRecipient](type-aliases/SplitRecipient.md) +- [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +- [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +- [BuilderRegistration](type-aliases/BuilderRegistration.md) +- [DepositData](type-aliases/DepositData.md) +- [DistributedValidator](type-aliases/DistributedValidator.md) +- [ClusterLock](type-aliases/ClusterLock.md) +- [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) + +## Functions + +- [validateClusterLock](functions/validateClusterLock.md) diff --git a/versioned_docs/version-v1.5/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.5/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..b57096a0bf --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +Cluster definition data needed for dkg + +## Extends + +- [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | `ClusterPayload.name` | types.ts:73 | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)[] | The cluster nodes operators addresses. | `ClusterPayload.operators` | types.ts:76 | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)[] | The cluster validators information. | `ClusterPayload.validators` | types.ts:79 | +| `deposit_amounts?` | `null` \| `string`[] | The cluster partial deposits in gwei or 32000000000. | `ClusterPayload.deposit_amounts` | types.ts:82 | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | types.ts:90 | +| `version` | `string` | The cluster configuration version. | - | types.ts:93 | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | types.ts:96 | +| `fork_version` | `string` | The cluster fork version. | - | types.ts:99 | +| `uuid` | `string` | The cluster uuid. | - | types.ts:102 | +| `timestamp` | `string` | The cluster creation timestamp. | - | types.ts:105 | +| `config_hash` | `string` | The cluster configuration hash. | - | types.ts:108 | +| `threshold` | `number` | The distributed validator threshold. | - | types.ts:111 | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | types.ts:114 | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | types.ts:117 | diff --git a/versioned_docs/version-v1.5/sdk/interfaces/README.md b/versioned_docs/version-v1.5/sdk/interfaces/README.md new file mode 100644 index 0000000000..b635dbc6dc --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# interfaces + diff --git a/versioned_docs/version-v1.5/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.5/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..4ee32df936 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,24 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +# RewardsSplitPayload + +OWR and Split Proxy Params + +### Extends + +* [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +### Properties + +| Property | Type | Description | Inherited from | Defined in | +| -------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ------------ | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)\[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | types.ts:136 | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for Obol protocol development fee, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | types.ts:139 | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | types.ts:142 | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | types.ts:145 | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | types.ts:153 | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | types.ts:156 | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | types.ts:159 | diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.5/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..281cd48a13 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +> **BuilderRegistration**: `object` + +Pre-generated Signed Validator Builder Registration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | types.ts:184 | +| `signature` | `string` | BLS signature of the builder registration message. | types.ts:187 | + +## Defined in + +types.ts:182 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.5/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..f7467b4436 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +> **BuilderRegistrationMessage**: `object` + +Unsigned DV Builder Registration Message + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient` | `string` | The DV fee recipient. | types.ts:167 | +| `gas_limit` | `number` | Default is 30000000. | types.ts:170 | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | types.ts:173 | +| `pubkey` | `string` | The public key of the DV. | types.ts:176 | + +## Defined in + +types.ts:165 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..643f98978e --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +> **ClusterCreator**: `object` + +Cluster creator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The creator address. | types.ts:52 | +| `config_signature`? | `string` | The cluster configuration signature. | types.ts:54 | + +## Defined in + +types.ts:50 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..e386f0060e --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +> **ClusterLock**: `object` + +Cluster Details after DKG is complete + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | types.ts:235 | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)[] | The cluster distributed validators. | types.ts:238 | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | types.ts:241 | +| `lock_hash` | `string` | The hash of the cluster lock. | types.ts:244 | +| `node_signatures`? | `string`[] | Node Signature for the lock hash by the node secp256k1 key. | types.ts:247 | + +## Defined in + +types.ts:233 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..c12e7caa48 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +> **ClusterOperator**: `object` + +Node operator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The operator address. | types.ts:23 | +| `enr`? | `string` | The operator ethereum node record. | types.ts:26 | +| `fork_version`? | `string` | The cluster fork_version. | types.ts:29 | +| `version`? | `string` | The cluster version. | types.ts:32 | +| `enr_signature`? | `string` | The operator enr signature. | types.ts:35 | +| `config_signature`? | `string` | The operator configuration signature. | types.ts:38 | + +## Defined in + +types.ts:21 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..ab4d99aff2 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +> **ClusterPayload**: `object` + +Cluster configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | types.ts:73 | +| `operators` | [`ClusterOperator`](ClusterOperator.md)[] | The cluster nodes operators addresses. | types.ts:76 | +| `validators` | [`ClusterValidator`](ClusterValidator.md)[] | The cluster validators information. | types.ts:79 | +| `deposit_amounts`? | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | types.ts:82 | + +## Defined in + +types.ts:71 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..266d48a113 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +> **ClusterValidator**: `object` + +Validator withdrawal configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | types.ts:62 | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | types.ts:65 | + +## Defined in + +types.ts:60 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.5/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..592d2f643b --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +> **DepositData**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | The public key of the distributed validator. | types.ts:195 | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | types.ts:198 | +| `amount` | `string` | 32 ethers. | types.ts:201 | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | types.ts:204 | +| `signature` | `string` | BLS signature of the deposit message. | types.ts:207 | + +## Defined in + +types.ts:193 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.5/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..5ec5dcc09d --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +> **DistributedValidator**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | types.ts:215 | +| `public_shares` | `string`[] | The public key of the node distributed validator share. | types.ts:218 | +| `deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\> | The deposit data for activating the DV. | types.ts:221 | +| `partial_deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\>[] | The deposit data with partial amounts or full amount for activating the DV. | types.ts:224 | +| `builder_registration`? | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | types.ts:227 | + +## Defined in + +types.ts:213 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.5/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..c08cb82c83 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +> **ETH\_ADDRESS**: `string` + +String expected to be Ethereum Address + +## Defined in + +types.ts:253 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.5/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..ee7810452c --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +> **OperatorPayload**: `Partial`\<[`ClusterOperator`](ClusterOperator.md)\> & `Required`\<`Pick`\<[`ClusterOperator`](ClusterOperator.md), `"enr"` \| `"version"`\>\> + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. + +## Defined in + +types.ts:44 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/README.md b/versioned_docs/version-v1.5/sdk/type-aliases/README.md new file mode 100644 index 0000000000..9e1ac60271 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# type-aliases + diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.5/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..e40db01a6c --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +> **SplitRecipient**: `object` + +Split Recipient Keys + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `account` | `string` | The split recipient address. | types.ts:125 | +| `percentAllocation` | `number` | The recipient split. | types.ts:128 | + +## Defined in + +types.ts:123 diff --git a/versioned_docs/version-v1.5/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.5/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..3e24994833 --- /dev/null +++ b/versioned_docs/version-v1.5/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +# TotalSplitPayload + +> **TotalSplitPayload**: `object` + +Split Proxy Params + +### Type declaration + +| Name | Type | Description | Defined in | +| -------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)\[] | The split recipients addresses and splits. | types.ts:136 | +| `ObolRAFSplit`? | `number` | Split percentageNumber allocated for Obol protocol development fee, minimum is 1%. | types.ts:139 | +| `distributorFee`? | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | types.ts:142 | +| `controllerAddress`? | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | types.ts:145 | + +### Defined in + +types.ts:134 diff --git a/versioned_docs/version-v1.5/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.5/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..5368c6e179 --- /dev/null +++ b/versioned_docs/version-v1.5/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# walkthroughs + diff --git a/versioned_docs/version-v1.5/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.5/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.5/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_docs/version-v1.6/README.md b/versioned_docs/version-v1.6/README.md new file mode 100644 index 0000000000..1cf9800b4e --- /dev/null +++ b/versioned_docs/version-v1.6/README.md @@ -0,0 +1,8 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "Introduction" +slug: /learn/readme +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..27650c3586 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# advanced + diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/add-validators.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/add-validators.md new file mode 100644 index 0000000000..ff55743164 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/add-validators.md @@ -0,0 +1,69 @@ +--- +description: "Add validators to your existing distributed validator cluster using the charon alpha add-validators command." +sidebar_label: "Adding Validators" +slug: /advanced-and-troubleshooting/advanced/add-validators +--- + +# Adding Validators + +:::warning +This is an experimental feature available starting with Charon v1.6 and should not be used in production (Mainnet) yet. +::: + +You can add validators to your cluster using the `charon alpha add-validators` command. The example below is designed for the default configuration provided by this repository and assumes that the stack uses the Lodestar validator client. + +## Prerequisites + +1. Review the `add-validators` command [CLI reference](https://docs.obol.org/docs/learn/charon/charon-cli-reference). +2. Ensure this folder contains a valid `.charon` directory currently used by the running node. Keep the DV node running during the process. + +## Adding Validators Process + +The examples below are for adding 10 validators. You can use them with any number of validators you would like to add. Run the following command to collectively generate and add 10 new validators with other node operators (similar to DKG): + +```bash +# If you prefer running a pre-built charon binary +charon alpha add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:latest alpha add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --data-dir=/opt/charon/.charon --output-dir=/opt/charon/output +``` + +This command will create a new cluster configuration that includes both existing and new validators. It will also generate the necessary keys for the new validators and deposit data files. The new configuration will be saved in the `output` directory. + +## Making the DV Stack Use the New Validators + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +1. To start using the new configuration (with the added validators), stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` and recognise all validators in the cluster. + +:::info +Steps 1–3 must be performed independently by all node operators, likely at different times. During this process, some nodes will use the old configuration and others the new one. Once the number of upgraded nodes reaches the BFT threshold, the newly added validators will begin participating in the cluster. +::: + +## Current Limitations + +- The new cluster configuration will not be reflected on the Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +- The `add-validators` command supports the KeyManager API (similar to the `dkg` command), but since it may not have direct access to the original private keys if they're not still in the `.charon` folder you are adding validators to, it cannot produce valid cluster lock signatures. In this case, you must use the `--unverified` flag, which means Charon does not hash and sign the new cluster lock file with all the private keys to prove their existence. This requires adding the `--no-verify` flag or `CHARON_NO_VERIFY=true` environment variable to the `charon run` command/container. +- If you use different validator clients, review the keys import script. The old keys in `.charon/validator_keys` remain unchanged, so verify that importing the same keys will not disrupt the validator client's state. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..91890c82c5 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 version-controlled 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 `tempo`. 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 +``` diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/beacon-node-authentication.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/beacon-node-authentication.md new file mode 100644 index 0000000000..ec63bbee2f --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/beacon-node-authentication.md @@ -0,0 +1,39 @@ +--- +description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control." +sidebar_label: "Beacon node authentication" +slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication +--- + +# Beacon node authentication + +## HTTP Basic Access Authentication + +If you want to use Charon with an [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic ` where `Authorization` will be the header key and `Basic ` will be the header value. The `` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`. + +:::warning +These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node. +::: + +## Usage example + +Suppose we have an HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command: + +``` +echo -n "john:doe" | base64 +``` + +Then you could pass the flag to your Charon instance like this: + +``` +charon run --beacon-node-headers="Authorization=Basic am9objpkb2U=" +``` + +Or you could specify it as an environment variable like this: + +``` +CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U=" +``` + +:::info +Note that 'Authorization' is followed with an `=` rather than the usual `:`. +::: diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/client-swap.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/client-swap.md new file mode 100644 index 0000000000..13ce4aa4dd --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/client-swap.md @@ -0,0 +1,174 @@ +--- +description: "Swap EL, CL, VC and MEV clients in the stack." +sidebar_label: "Client Swap" +slug: /advanced-and-troubleshooting/advanced/client-swap +--- + +# Client swap + +If you are using CDVN, the default stack is: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | --------- | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | + +However, to achieve greater resilience through client diversity, it is preferred to run a variety of clients across your cluster, ideally ensuring no single EL/CL/VC runs on one third of the nodes or more. CDVN supports changing from the default clients. + +Currently supported client options are: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | ------------ | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | +| | Grandine | | Nimbus | Commit boost | +| | | | Prysm | | +| | | | Teku | | + +For support between different combinations, refer to Charon's compatibility matrix, found in the [prepare section of the docs](../../run-a-dv/prepare/how_where_dvs.md) or under [release notes](https://github.com/ObolNetwork/charon/releases/) for each release. + +:::info +As CDVN natively supports more clients, the number of possible combinations grows quickly. +We test extensively, but cannot guarantee the performance of all possible client combos. +If you run a mixed-client cluster, monitor performance and be ready to swap to another client if you observe issues. +::: + +## Choosing clients in fresh cluster + +In order to choose which clients to use in a new cluster, simply leave uncommented (only) the desired `EL`, `CL`, `MEV` or `VC` variables in the `.env` file. There must be only one client per component. The cluster will use the respective client for each component. + +## Swapping clients in an already running cluster + +:::warning +For ([L](https://github.com/obolNetwork/lido-charon-distributed-validator-node))[CDVN](https://github.com/obolNetwork/charon-distributed-validator-node) users who created their `.env` file before the release of charon `v1.6.1`, there are breaking changes between then and the current multi-client `.env` file setup. +The minimal addition to an older version of the `.env` file compatible with the current versions of the repos is to add `COMPOSE_PROFILES=el_nethermind,cl_lighthouse,dv_charon,vc_lodestar,mev_mevboost` to your existing `.env` file. +Some environment variables were renamed in order to be client-agnostic. **If you had set these environment variables to custom values in your `.env`, you need to set the new variables to your custom values**. They serve the same purpose. + +| Old | New | +|-------------------------------|--------------------------------- | +| NETHERMIND_PORT_P2P | EL_PORT_P2P | +| NETHERMIND_IP_HTTP | EL_IP_HTTP | +| NETHERMIND_PORT_HTTP | EL_PORT_HTTP | +| NETHERMIND_IP_ENGINE | EL_IP_ENGINE | +| NETHERMIND_PORT_ENGINE | EL_PORT_ENGINE | +| LIGHTHOUSE_PORT_P2P | CL_PORT_P2P | +| LODESTAR_PORT_METRICS | VC_PORT_METRICS | +| MEVBOOST_TIMEOUT_GETHEADER | MEV_TIMEOUT_GETHEADER | +| MEVBOOST_TIMEOUT_GETPAYLOAD | MEV_TIMEOUT_GETPAYLOAD | +| MEVBOOST_TIMEOUT_REGVAL | MEV_TIMEOUT_REGVAL | +| MEVBOOST_RELAYS | MEV_RELAYS | +| NETHERMIND_PROMTAIL_MONITORED | EL_NETHERMIND_PROMTAIL_MONITORED | +| LIGHTHOUSE_PROMTAIL_MONITORED | CL_LIGHTHOUSE_PROMTAIL_MONITORED | +| LODESTAR_PROMTAIL_MONITORED | VC_LODESTAR_PROMTAIL_MONITORED | +| MEV_BOOST_PROMTAIL_MONITORED | MEV_MEV_BOOST_PROMTAIL_MONITORED | + +::: + +1. Copy the new `.env.sample.` file to `.env`. +2. Comment or uncomment your preferred Execution, Consensus, Validator, and MEV clients and save the file. +3. Stop the existing cluster that uses the old environment file. + +```sh +docker compose --profile "" down +``` + +3. Start the node again to pick up the changes to the `.env` file. + +```sh +docker compose up -d +``` + +Your node should start up with the new clients. + +### Swap Consensus layer + +:::info +The code snippets under those steps are assuming you are swapping from Lighthouse CL to Grandine CL and you. +::: + +1. Stop the existing consensus layer client container. + +:::info +If you do not want to experience downtime while the new beacon node is syncing, you can set a fallback beacon node for Charon (`CHARON_FALLBACK_BEACON_NODE_ENDPOINTS` env variable) that will be used while the new BN is syncing. +Note that you need to restart Charon as well in order for it to take effect. +::: + +```sh +docker compose down cl-lighthouse +``` + +1. Comment out the currently set `CL` environment variable in `.env` (i.e.: `CL=cl-lighthouse` -> `#CL=cl-lighthouse`). Uncomment the desired CL (i.e.: `#CL=cl-grandine` -> `CL=cl-grandine`). + +2. Start the new consensus layer client container. + +```sh +docker compose up cl-grandine -d +``` + +4. Restart Charon in order to update the CL client it's querying. + +```sh +docker compose down charon +docker compose up charon -d +``` + +5. After the new consensus layer client is synced and you are assured the new setup is working, you can delete the previous CL client's data in order to save resources. + +```sh +rm -rf ./data/lighthouse +``` + +### Swap Validator client + +:::info +The code snippets under those steps are assuming you are swapping from Lodestar VC to Teku VC. +::: + +1. Stop the existing validator client container. + +```sh +docker compose down vc-lodestar +``` + +2. Comment out the currently set `VC` environment variable in `.env` (i.e.: `VC=vc-lodestar` -> `#VC=vc-lodestar`). Uncomment the desired VC (i.e.: `#VC=vc-teku` -> `VC=vc-teku`). + +3. Start the new validator client container. + +```sh +docker compose up vc-teku -d +``` + +4. After the new validator client is started and you are assured the new setup is working, you can delete the previous VC's data in order to save resources + +```sh +rm -rf ./data/lodestar +``` + +### SWAP MEV client + +:::info +The code snippets under those steps are assuming you are swapping from MEV Boost to Commit Boost and you are using Lighthouse CL. +::: + +:::info +If switching to Commit Boost, you will need to copy a Commit Boost TOML config `commit-boost/config.toml.sample.` to `commit-boost/config.toml`, as it does not support `.env` configurations yet. Make sure the configuration matches what you have had set for mev-boost, in terms of relays and timeouts. +::: + +1. Stop the existing MEV client container. + +```sh +docker compose down mev-mevboost +``` + +2. Comment out the currently set `MEV` environment variable in `.env` (i.e.: `MEV=mev-mevboost` -> `#MEV=mev-mevboost`). Uncomment the desired MEV (i.e.: `#MEV=mev-commitboost` -> `MEV=mev-commitboost`). + +3. Start the new MEV client container. + +```sh +docker compose up mev-commitboost -d +``` + +4. Restart the beacon node in order to update the MEV it's querying. + +```sh +docker compose down cl-lighthouse +docker compose up cl-lighthouse -d +``` diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..cb8e916119 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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](https://docs.obol.org/next/learn/intro/launchpad). + +### Pre-requisites[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#pre-requisites) {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#install-the-package) {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#instantiate-the-client) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#propose-the-cluster) {#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. + +```sh +// 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#invite-the-operators-to-complete-the-dkg) {#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](https://docs.obol.org/next/learn/intro/launchpad) to complete the process + +1. Operators navigate to `https://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](https://docs.obol.org/next/run/start/quickstart_group) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#retrieve-the-created-distributed-validators-using-the-sdk) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#activate-the-dvs-using-the-deposit-contract) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#usage-examples) {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/custom-graffiti.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/custom-graffiti.md new file mode 100644 index 0000000000..567abf7ad0 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/custom-graffiti.md @@ -0,0 +1,20 @@ +--- +description: "Add custom graffiti to your block proposals" +sidebar_label: "Custom Graffiti" +slug: /advanced-and-troubleshooting/advanced/custom-graffiti +--- + +# Custom Graffiti + +By default, Charon adds a `charon/-` graffiti to all block proposals. This can be customized using the `--graffiti` and `--graffiti-disable-client-append` CLI flags. + +The `--graffiti` flag accepts either: + +* A single string, which will be used by all validators, or +* A comma-separated list of strings, allowing each validator to have a unique graffiti (one string per validator). + +When possible, Charon automatically appends an Obol signature (`OB`) and the specific consensus client type used (``) to the end of the custom graffiti. This behavior can be disabled by setting the `--graffiti-disable-client-append` flag. + +:::info +The graffiti field in block proposals has a maximum size of 32 bytes. +::: diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..f7e0c6e6de --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#getting-started-with-charon--the-builder-api) {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#client-configuration) {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#charon) {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#consensus-clients) {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](https://docs.obol.org/next/run/prepare/test-command#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#validator-clients) {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#verify-your-cluster-is-correctly-configured) {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [Ultrasound Relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. If you are using [Titan Relay](https://titanrelay.xyz), you can check their API by running `curl https://titanrelay.xyz/relay/v1/data/validator_registration?pubkey=0x123..456` with the public key of a validator in your cluster. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/enable-tls-protocol.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/enable-tls-protocol.md new file mode 100644 index 0000000000..c822a27225 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/enable-tls-protocol.md @@ -0,0 +1,37 @@ +--- +description: "Enable the TLS protocol to secure HTTPS requests made by the Validator Client to Charon." +sidebar_label: "Enable TLS Protocol" +slug: /advanced-and-troubleshooting/advanced/enable-tls-protocol +--- + +# Enable TLS protocol + +## Securing VC to Charon communication + +To secure the communication between the Validator Client and Charon, you can enable the TLS protocol in Charon's HTTP server. This only affects [Beacon API](https://ethereum.github.io/beacon-APIs/) endpoints and not debug/metrics endpoints. As an operator of the node, you need to have a TLS certificate and a private key that signed this certificate or CSR. Then you need to configure Charon to use them. +## Usage example + +Suppose we don't have a TLS certificate and a key yet. We can create a self-signed certificate and a key using OpenSSL: + +``` +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +Then you could pass the flags to your Charon instance like this: + +``` +charon run --vc-tls-cert-file cert.pem --vc-tls-key-file key.pem +``` + +Charon accepts a certificate in PEM or CRT formats and the private key in PEM or DER formats. + +Also you can specify these parameters as environment variables like this: + +``` +CHARON_VC_TLS_CERT_FILE="cert.pem" +CHARON_VC_TLS_KEY_FILE="key.pem" +``` + +On the Validator Client (VC) side, no additional configuration is typically required. The VC will automatically use the TLS protocol when communicating with Charon. However, if the TLS certificate is signed by a custom or non-standard certificate authority (CA), you may need to configure the VC to trust this CA. This can usually be achieved by adding the CA's certificate to the trusted certificate store on the machine running the VC. + +If necessary, you can also enable `insecure` mode in the VC configuration to bypass TLS verification. Note that this approach is not recommended for production environments as it compromises security. Detailed instructions for configuring specific Validator Clients are beyond the scope of this article. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md new file mode 100644 index 0000000000..7f301659c6 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md @@ -0,0 +1,13 @@ +--- +description: "Add fallback beacon nodes to use when primary beacon node fails" +sidebar_label: "Fallback Beacon Nodes" +slug: /advanced-and-troubleshooting/advanced/fallback-beacon-nodes +--- + +# Fallback beacon nodes + +Charon allows specifying multiple beacon node URL endpoints. It sends requests to all specified endpoints simultaneously and proceeds with the first response received. This approach improves reliability but increases the load on the beacon nodes. + +To mitigate this additional load, Charon supports configuring a fallback list of beacon nodes. These fallback nodes are only used if all primary beacon nodes fail to respond. This allows operators to designate less critical or public beacon nodes as a backup option, without impacting them under normal conditions. + +To configure fallback beacon nodes, provide a comma-separated list of beacon node URLs using the `--fallback-beacon-node-endpoints` CLI flag. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/nicknames.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/nicknames.md new file mode 100644 index 0000000000..9606a46788 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/nicknames.md @@ -0,0 +1,18 @@ +--- +description: "Add a nickname to your Charon node" +sidebar_label: "Nicknames" +slug: /advanced-and-troubleshooting/advanced/nicknames +--- + +# Nicknames + +By default, Charon assigns each node a name by combining a random adjective with a random name from a predefined list. While these names are human-readable, they are not easily memorable or personalised for operators. + +You can set a personalised nickname for your Charon node by using the `--nickname` CLI flag followed by the desired string. This nickname is shared with other Charon nodes in the same cluster and included as a label in your Prometheus metrics. + +Nicknames can serve various purposes, such as providing a more memorable identifier, including a Discord ID for alerting, or adding a website URL for publicity. + + + + + diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..19a8ac8e53 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.6.1 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. +::: diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..42a502db40 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,110 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +:::info +Starting with Charon v1.6.1, you may not need to manually prepare the keystore files as described below. Charon can recursively search for keystore files in the specified directory and attempt to match the corresponding password files. The only case where this does not work is when you specify an exact list of withdrawal addresses; in that case, you must prepare the files manually and ensure the keystore indices match the order of the specified withdrawal addresses. +::: + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.6.1 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet \ + --publish +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..8c80d667f8 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,38 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency and decentralization, you can opt to host your own relay on a separate open and static internet port. + +```shell +# Figure out your public IP +curl v4.ident.me + +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your public IPv4 or DNS hostname + +nano relay/docker-compose.yml + +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +Note that a local `relay/.charon/charon-enr-private-key` file will be created next to `relay/docker-compose.yml` to ensure a persisted relay ENR across restarts. + +A list of publicly available relays that can be used is maintained [here](../security/risks.md). diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/README.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/README.md new file mode 100644 index 0000000000..08d9fd5147 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Security" +slug: /advanced-and-troubleshooting/security +--- + +# security + diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/bug-bounty.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/bug-bounty.md new file mode 100644 index 0000000000..06a57d0d34 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/bug-bounty.md @@ -0,0 +1,181 @@ +--- +description: "Bug Bounty Policy" +sidebar_label: "Obol Bug Bounty Program" +slug: /advanced-and-troubleshooting/security/bug-bounty +--- + +# Obol Bug Bounty Program + +## Overview + +At Obol Labs, we prioritize the security of our distributed validator software and related services. Our Bug Bounty Program is designed to encourage and reward security researchers for identifying and reporting potential vulnerabilities. This initiative supports our commitment to the security and integrity of our products. + +## Participant Eligibility + +Participants must meet the following criteria to be eligible for the Bug Bounty Program: + +- Not reside in countries where participation in such programs is prohibited. +- Be at least 14 years of age and possess the legal capacity to participate. +- Have received consent from your employer, if applicable. +- Not have been employed or contracted by Obol Labs, nor be an immediate family member of an employee, within the last 12 months. + +## Scope of the Program + +Eligible submissions must involve software and services developed by Obol, specifically under the domains of: + +- Charon the DV Middleware Client +- Obol DV Launchpad and Public API +- Obol Splits Contracts +- Obol Labs hosted Public Relay Infrastructure + +Submissions related to the following are considered out of scope: + +- Social engineering +- Rate Limiting (Non-critical issues) +- Physical security breaches +- Non-security related UX/UI issues +- Third-party application vulnerabilities +- The [Obol](https://obol.org) static website or the Obol infrastructure +- The operational security of node operators running or using Obol software + +## Program Rules + +- Submitted bugs must not have been previously disclosed publicly. +- Only first reports of vulnerabilities will be considered for rewards; previously reported or known vulnerabilities are ineligible. +- The severity of the vulnerability, as assessed by our team, will determine the reward amount. See the "Rewards" section for details. +- Submissions must include a reproducible proof of concept. +- The Obol security team reserves the right to determine the eligibility and reward for each submission. +- Program terms may be updated at Obol's discretion. +- Valid bugs may be disclosed to partner protocols within the Obol ecosystem to enhance overall security. + +## Rewards Structure + +Rewards are issued based on the severity and impact of the disclosed vulnerability, determined at the discretion of Obol Labs. + +### Critical Vulnerabilities: Up to $100,000 + +A Critical-level vulnerability is one that has a severe impact on the security of the in-production system from an unauthenticated external attacker, and requires immediate attention to fix. Highly likely to have a material impact on validator private key security, and/or loss of funds. + +- High impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully exfiltrate BLS (not K1) private key material from a threshold number of operators in the cluster. +- Attacker that is not a member of the cluster can achieve the production of arbitrary BLS signatures from a threshold number of operators in the cluster. +- Attacker can craft a malicious cluster invite capable of subverting even careful review of all data to steal funds during a deposit. +- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield +- Direct loss of funds +- Permanent freezing of funds (fix requires hard fork) +- Network not being able to confirm new transactions (Total network shutdown) +- Protocol insolvency + +### High Vulnerabilities: Up to $10,000 + +For significant security risks that impact the system from a position of low-trust and require a significant effort to fix. + +- High impact, medium likelihood +- Medium impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully partition the cluster and keep the cluster offline indefinitely. +- Attacker that is not a member of the cluster can exfiltrate Charon ENR private keys. +- Attacker that is not a member of the cluster can destroy funds but cannot steal them. +- Unintended chain split (Network partition) +- Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments +- RPC API crash affecting projects with greater than or equal to 25% of the market capitalization on top of the respective layer +- Theft of unclaimed yield +- Theft of unclaimed royalties +- Permanent freezing of unclaimed yield +- Permanent freezing of unclaimed royalties +- Temporary freezing of funds +- Retrieve sensitive data/files from a running server: + - blockchain keys + - database passwords + - (this does not include non-sensitive environment variables, open source code, or usernames) +- Taking state-modifying authenticated actions (with or without blockchain state interaction) on behalf of other users without any interaction by that user, such as: + - Changing cluster information + - Withdrawals + - Making trades + +### Medium Vulnerabilities: Up to $2,500 + +For vulnerabilities with a moderate impact, affecting system availability or integrity. + +- High impact, low likelihood +- Medium impact, medium likelihood +- Low impact, high likelihood + +Impacts: + +- Attacker that is a member of a cluster can exfiltrate K1 key material from another member. +- Attacker that is a member of the cluster can denial of service attack enough peers in the cluster to prevent operation of the validator(s) +- Attacker that is a member of the cluster can bias the protocol in a manner to control the majority of block proposal opportunities. +- Attacker can get a DV Launchpad user to inadvertently interact with a smart contract that is not a part of normal operation of the launchpad. +- Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours +- Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network +- Charon cluster identity private key theft +- Rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle +- Charon public relay node is compromised and leads to cluster topologies getting discovered and disrupted +- Smart contract unable to operate due to lack of token funds +- Block stuffing +- Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol) +- Theft of gas +- Unbounded gas consumption +- Redirecting users to malicious websites (Open Redirect) + +### Low Vulnerabilities: Up to $500 + +For vulnerabilities with minimal impact, unlikely to significantly affect system operations. + +- Low impact, medium likelihood +- Medium impact, low likelihood + +Impacts: + +- Attacker can sometimes put a Charon node in a state that causes it to drop one out of every one hundred attestations made by a validator +- Attacker can display bad data on a non-interactive part of the launchpad. +- Contract fails to deliver promised returns, but doesn't lose value +- Shutdown of greater than 10% or equal to but less than 30% of network processing nodes without brute force actions, but does not shut down the network +- Changing details of other users (including modifying browser local storage) without already-connected wallet interaction and with significant user interaction such as: + - Iframing leading to modifying the backend/browser state (must demonstrate impact with PoC) +- Taking over broken or expired outgoing links such as: + - Social media handles, etc. +- Temporarily disabling user to access target site, such as: + - Locking up the victim from login + - Cookie bombing, etc. + +Rewards may be issued as cash, merchandise, or other forms of recognition, at Obol's discretion. Only one reward will be granted per unique vulnerability. + +## The following activities are prohibited by this bug bounty program + +- Any testing on mainnet or public testnet deployed code; all testing should be done on local-forks of either public testnet or mainnet +- Any testing with pricing oracles or third-party smart contracts +- Attempting phishing or other social engineering attacks against our employees and/or customers +- Any testing with third-party systems and applications (e.g. browser extensions) as well as websites (e.g. SSO providers, advertising networks) +- Any denial of service attacks that are executed against project assets +- Automated testing of services that generate significant amounts of traffic +- Public disclosure of an unpatched vulnerability in an embargoed bounty + +## Submission process + +To report a vulnerability, please contact us at security@obol.tech with: + +- A detailed description of the vulnerability and its potential impact. +- Steps to reproduce the issue. +- Any relevant proof of concept code, screenshots, or documentation. +- Your contact information. + +Incomplete reports may not be eligible for rewards. + +## Disclosure and Confidentiality + +Obol Labs will disclose vulnerabilities and the identity of the researcher (with consent) after remediation. Researchers are required to maintain confidentiality until official disclosure by Obol Labs. + +## Legal and Ethical Compliance + +Participants must adhere to all relevant laws and regulations. Obol Labs will not pursue legal action against researchers reporting vulnerabilities in good faith, but reserves the right to respond to violations of this policy. + +## Non-Disclosure Agreement (NDA) + +Participants may be required to sign an NDA for access to certain proprietary information during their research. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/contact.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/contact.md new file mode 100644 index 0000000000..0b4b54d4fd --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/contact.md @@ -0,0 +1,11 @@ +--- +description: "Security details for the Obol Network" +sidebar_label: "Contacts" +slug: /advanced-and-troubleshooting/security/contact +--- + +# Contacts + +Please email security@obol.tech to report a security incident, vulnerability, bug or inquire about Obol's security. + +Also, visit the [obol security repo](https://github.com/ObolNetwork/obol-security) for more details. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/ev-assessment.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/ev-assessment.md new file mode 100644 index 0000000000..969839bde3 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/ev-assessment.md @@ -0,0 +1,293 @@ +--- +description: "Software Development Security Assessment" +sidebar_label: "Software Development at Obol" +slug: /advanced-and-troubleshooting/security/ev-assessment +--- + +# Software Development at Obol + +When hardening a project's technical security, team member's operational security, and the security of the software development practices in use by the team are some of the most critical areas to secure. Many hacks and compromises in the space to date have been a result of these attack vectors rather than exploits of the software itself. + +With this in mind, in January 2023 the Obol team retained the expertise of Ethereal Venture's security researcher Alex Wade; to interview key stakeholders and produce a report into the team's Software Development Lifecycle. + +The below page is a result of the report that was produced. What is present here has had some sensitive information redacted, and contains responses to the recommendations made, detailing the actions the Obol team have taken to mitigate what has been highlighted. + +## Obol Report + +**Prepared by: Alex Wade (Ethereal Ventures)** **Date: Jan 2023** + +Over the past month, I worked with Obol to review their software development practices in preparation for their upcoming security audits. My goals were to review and analyze: + +* Software development processes +* Vulnerability disclosure and escalation procedures +* Key personnel risk + +The information in this report was collected through a series of interviews with Obol’s project leads. + +## Contents + +* Background Info +* Analysis - Cluster Setup and DKG + * Key Risks + * Potential Attack Scenarios +* Recommendations + * R1: Users should deploy cluster contracts through a known on-chain entry point + * R2: Users should deposit to the beacon chain through a pool contract + * R3: Raise the barrier to entry to push an update to the Launchpad +* Additional Notes + * Vulnerability Disclosure + * Key Personnel Risk + +## Background Info + +**Each team lead was asked to describe Obol in terms of its goals, objectives, and key features.** + +### What is Obol? + +Obol builds DVT (Distributed Validator Technology) for Ethereum. + +### What is Obol’s goal? + +Obol’s goal is to solve a classic distributed systems problem: uptime. + +Rather than requiring Ethereum validators to stake on their own, Obol allows groups of operators to stake together. Using Obol, a single validator can be run cooperatively by multiple people across multiple machines. + +In theory, this architecture provides validators with some redundancy against common issues: server and power outages, client failures, and more. + +### What are Obol’s objectives? + +Obol’s business objective is to provide base-layer infrastructure to support a distributed validator ecosystem. As Obol provides base layer technology, other companies and projects will build on top of Obol. + +Obol’s business model is to eventually capture a portion of the revenue generated by validators that use Obol infrastructure. + +### What is Obol’s product? + +Obol’s product consists of three main components, each run by its own team: a webapp, a client, and smart contracts. + +* [DV Launchpad](../../learn/intro/launchpad.md): A webapp to create and manage distributed validators. +* [Charon](../../learn/charon/intro.md): A middleware client that enables operators to run distributed validators. +* [Solidity](../../learn/intro/obol-splits.md): Withdrawal and fee recipient contracts for use with distributed validators. + +## Analysis - Cluster Setup and DKG + +The Launchpad guides users through the process of creating a cluster, which defines important parameters like the validator’s fee recipient and withdrawal addresses, as well as the identities of the operators in the cluster. In order to ensure their cluster configuration is correct, users need to rely on a few different factors. + +**First, users need to trust the Charon client** to perform the DKG correctly, and validate things like: + +* Config file is well-formed and is using the expected version +* Signatures and ENRs from other operators are valid +* Cluster config hash is correct +* DKG succeeds in producing valid signatures +* Deposit data is well-formed and is correctly generated from the cluster config and DKG. + +However, Charon’s validation is limited to the digital: signature checks, cluster file syntax, etc. It does NOT help would-be operators determine whether the other operators listed in their cluster definition are the real people with whom they intend to start a DVT cluster. So - + +**Second, users need to come to social consensus with fellow operators.** While the cluster is being set up, it’s important that each operator is an active participant. Each member of the group must validate and confirm that: + +* the cluster file correctly reflects their address and node identity, and reflects the information they received from fellow operators +* the cluster parameters are expected – namely, the number of validators and signing threshold + +**Finally, users need to perform independent validation.** Each user should perform their own validation of the cluster definition: + +* Is my information correct? (address and ENR) +* Does the information I received from the group match the cluster definition? +* Is the ETH2 deposit data correct, and does it match the information in the cluster definition? +* Are the withdrawal and fee recipient addresses correct? + +These final steps are potentially the most difficult, and may require significant technical knowledge. + +## Key Risks + +### 1. Validation of Contract Deployment and Deposit Data Relies Heavily on Launchpad + +From my interviews, it seems that the user deploys both the withdrawal and fee recipient contracts through the Launchpad. + +What I’m picturing is that during the first parts of the cluster setup process, the user is prompted to sign one or more transactions deploying the withdrawal and fee recipient contracts to mainnet. The Launchpad apparently uses an npm package to deploy these contracts: `0xsplits/splits-sdk`, which I assume provides either JSON artifacts or a factory address on chain. The Launchpad then places the deployed contracts into the cluster config file, and the process moves on. + +If an attacker has published a malicious update to the Launchpad (or compromised an underlying dependency), the contracts deployed by the Launchpad may be malicious. The questions I’d like to pose are: + +* How does the group creator know the Launchpad deployed the correct contracts? +* How does the rest of the group know the creator deployed the contracts through the Launchpad? + +My understanding is that this ultimately comes down to the independent verification that each of the group’s members performs during and after the cluster’s setup phase. + +At its worst, this verification might consist solely of the cluster creator confirming to the others that, yes, those addresses match the contracts I deployed through the Launchpad. + +A more sophisticated user might verify that not only do the addresses match, but the deployed source code looks roughly correct. However, this step is far out of the realm of many would-be validators. To be really certain that the source code is correct would require auditor-level knowledge. + +The risk is that: + +* the deployed contracts are NOT the correctly-configured 0xsplits waterfall/fee splitter contracts +* most users are ill-equipped to make this determination themselves +* we don’t want to trust the Launchpad as the single source of truth + +In the worst case, the cluster may end up depositing with malicious withdrawal or fee recipient credentials. If unnoticed, this may net an attacker the entire withdrawal amount, once the cluster exits. + +Note that the same (or similar) risks apply to validation of deposit data, which has the potential to be similarly difficult. I’m a little fuzzy on which part of the Obol stack actually generates the deposit data / deposit transaction, so I can’t speak to this as much. However, I think the mitigation for both of these is roughly the same - read on! + +**Mitigation:** + +It’s certainly a good idea to make it harder to deploy malicious updates to the Launchpad, but this may not be entirely possible. A higher-yield strategy may be to educate and empower users to perform independent validation of the DVT setup process - without relying on information fed to them by Charon and the Launchpad. + +I’ve outlined some ideas for this in #R1 and #R2. + +### 2. Social Consensus, aka “Who sends the 32 ETH?” + +Depositing to the beacon chain requires a total of 32 ETH. Obol’s product allows multiple operators to act as a single validator together, which means would-be operators need to agree on how to fund the 32 ETH needed to initiate the deposit. + +It is my understanding that currently, this process comes down to trust and loose social consensus. Essentially, the group needs to decide who chips in what amount together, and then trust someone to take the 32 ETH and complete the deposit process correctly (without running away with the money). + +Granted, the initial launch of Obol will be open only to a small group of people as the kinks in the system get worked out - but in preparation for an eventual public release, the deposit process needs to be much simpler and far less reliant on trust. + +Mitigation: See #R2. + +**Potential Attack Scenarios** + +During the interview process, I learned that each of Obol’s core components has its own GitHub repo, and that each repo has roughly the same structure in terms of organization and security policies. For each repository: + +* There are two overall github organization administrators, and a number of people have administrative control over individual repositories. +* In order to merge PRs, the submitter needs: + * CI/CD checks to pass + * Review from one person (anyone at Obol) + +Of course, admin access also means the ability to change these settings - so repo admins could theoretically merge PRs without needing checks to pass, and without review/approval, organization admins can control the full GitHub organization. + +The following scenarios describe the impact an attack may have. + +**1. Publishing a malicious version of the Launchpad, or compromising an underlying dependency** + +* Reward: High +* Difficulty: Medium-Low + +As described in Key Risks, publishing a malicious version of the Launchpad has the potential to net the largest payout for an attacker. By tampering with the cluster’s deposit data or withdrawal/fee recipient contracts, an attacker stands to gain 32 ETH or more per compromised cluster. + +During the interviews, I learned that merging PRs to main in the Launchpad repo triggers an action that publishes to the site. Given that merges can be performed by an authorized Obol developer, this makes the developers prime targets for social engineering attacks. + +Additionally, the use of the `0xsplits/splits-sdk` NPM package to aid in contract deployment may represent a supply chain attack vector. It may be that this applies to other Launchpad dependencies as well. + +In any case, with a fairly large surface area and high potential reward, this scenario represents a credible risk to users during the cluster setup and DKG process. + +See #R1, #R2, and #R3 for some ideas to address this scenario. + +**2. Publishing a malicious version of Charon to new operators** + +* Reward: Medium +* Difficulty: High + +During the cluster setup process, Charon is responsible both for validating the cluster configuration produced by the Launchpad, as well as performing a DKG ceremony between a group’s operators. + +If new operators use a malicious version of Charon to perform this process, it may be possible to tamper with both of these responsibilities, or even get access to part or all of the underlying validator private key created during DKG. + +However, the difficulty of this type of attack seems quite high. An attacker would first need to carry out the same type of social engineering attack described in scenario 1 to publish and tag a new version of Charon. Crucially, users would also need to install the malicious version - unlike the Launchpad, an update here is not pushed directly to users. + +As long as Obol is clear and consistent with communication around releases and versioning, it seems unlikely that a user would both install a brand-new, unannounced release, and finish the cluster setup process before being warned about the attack. + +**3. Publishing a malicious version of Charon to existing validators** + +* Reward: Low +* Difficulty: High + +Once a distributed validator is up and running, much of the danger has passed. As a middleware client, Charon sits between a validator’s consensus and validator clients. As such, it shouldn’t have direct access to a validator’s withdrawal keys nor signing keys. + +If existing validators update to a malicious version of Charon, it’s likely the worst thing an attacker could theoretically do is slash the validator, however, assuming Charon has no access to any private keys, this would be predicated on one or more validator clients connected to Charon also failing to prevent the signing of a slashable message. In practice, a compromised Charon client is more likely to pose liveness risks than safety risks. + +This is not likely to be particularly motivating to potential attackers - and paired with the high difficulty described above, this scenario seems unlikely to cause significant issues. + +## Recommendations + +### R1: Users should deploy cluster contracts through a known on-chain entry point + +During setup, users should only sign one transaction via the Launchpad - to a contract located at an Obol-held ENS (e.g. `launchpad.obol.eth`). This contract should deploy everything needed for the cluster to operate, like the withdrawal and fee recipient contracts. It should also initialize them with the provided reward split configuration (and any other config needed). + +Rather than using an NPM library to supply a factory address or JSON artifacts, this has the benefit of being both: + +* **Harder to compromise:** as long as the user knows launchpad.obol.eth, it’s pretty difficult to trick them into deploying the wrong contracts. +* **Easier to validate** for non-technical users: the Obol contract can be queried for deployment information via etherscan. For example:\ + ![](/img/gitbook/image-50.png) + +Note that in order for this to be successful, Obol needs to provide detailed steps for users to perform manual validation of their cluster setups. Users should be able to treat this as a “checklist:” + +* Did I send a transaction to `launchpad.obol.eth`? +* Can I use the ENS name to locate and query the deployment manager contract on etherscan? +* If I input my address, does etherscan report the configuration I was expecting? + * withdrawal address matches + * fee recipient address matches + * reward split configuration matches + +As long as these steps are plastered all over the place (i.e. not just on the Launchpad) and Obol puts in effort to educate users about the process, this approach should allow users to validate cluster configurations themselves - regardless of Launchpad or NPM package compromise. + +**Obol’s response** + +Roadmapped: add the ability for the OWR factory to claim and transfer its reverse resolution ownership. + +### R2: Users should deposit to the beacon chain through a pool contract + +Once cluster setup and DKG is complete, a group of operators should deposit to the beacon chain by way of a pool contract. The pool contract should: + +* Accept Eth from any of the group’s operators +* Stop accepting Eth when the contract’s balance hits (32 ETH \* number of validators) +* Make it easy to pull the trigger and deposit to the beacon chain once the critical balance has been reached +* Offer all of the group’s operators a “bail” option at any point before the deposit is triggered + +Ideally, this contract is deployed during the setup process described in #R1, as another step toward allowing users to perform independent validation of the process. + +Rather than relying on social consensus, this should: + +* Allow operators to fund the validator without needing to trust any single party +* Make it harder to mess up the deposit or send funds to some malicious actor, as the pool contract should know what the beacon deposit contract address is + +**Obol’s response** + +Roadmapped: give the operators a streamlined, secure way to deposit Ether (ETH) to the beacon chain collectively, satisfying specific conditions: + +* Pooling from multiple operators. +* Ceasing to accept ETH once a critical balance is reached, defined by 32 ETH multiplied by the number of validators. +* Facilitating an immediate deposit to the beacon chain once the target balance is reached. +* Provide a 'bail-out' option for operators to withdraw their contribution before initiating the group's deposit to the beacon chain. + +### R3: Raise the barrier to entry to push an update to the Launchpad + +Currently, any repo admin can publish an update to the Launchpad unchecked. + +Given the risks and scenarios outlined above, consider amending this process so that the sole compromise of either admin is not sufficient to publish to the Launchpad site. It may be worthwhile to require both admins to approve publishing to the site. + +Along with simply adding additional prerequisites to publish an update to the Launchpad, ensure that both admins have enabled some level of multi-factor authentication on their GitHub accounts. + +**Obol’s response** + +We removed individual’s ability to merge changes without review, enforced MFA, signed commits, and employed Bulldozer bot to make sure a PR gets merged automatically when all checks pass. + +## Additional Notes + +### Vulnerability Disclosure + +During the interviews, I got some conflicting information when asking about Obol’s vulnerability disclosure process. + +Some interviewees directed me towards Obol’s security repo, which details security contacts: [ObolNetwork/obol-security](https://github.com/ObolNetwork/obol-security), while some answered that disclosure should happen primarily through Immunefi. While these may both be part of the correct answer, it seems that Obol’s disclosure process may not be as well-defined as it could be. Here are some notes: + +* I wasn’t able to find information about Obol on Immunefi. I also didn’t find any reference to a security contact or disclosure policy in Obol’s docs. +* When looking into the obol security repo, I noticed broken links in a few of the sections in README.md and SECURITY.md: + * Security policy + * More Information +* Some of the text and links in the Bug Bounty Program don’t seem to apply to Obol (see text referring to Vaults and Strategies). +* The Receiving Disclosures section does not include a public key with which submitters can encrypt vulnerability information. + +It’s my understanding that these items are probably lower priority due to Obol’s initial closed launch - but these should be squared away soon! \[Obol response to latest vuln disclosure process goes here] + +**Obol’s response** + +we addressed all of the concerns in the obol-security repository: + +1. The security policy link has been fixed +2. The Bug Bounty program received an overhaul and clearly states rewards, eligibility, and scope +3. We list two GPG public keys for which we accept encrypted vulnerabilities reports. + +We are actively working towards integrating Immunefi in our security pipeline. + +### Key Personnel Risk + +A final section on the specifics of key personnel risk faced by Obol has been redacted from the original report. Particular areas of control highlighted were github org ownership and domain name control. + +**Obol’s response** + +These risks have been mitigated by adding an extra admin to the github org, and by setting up a second DNS stack in case the primary one fails, along with general Opsec improvements. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/overview.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/overview.md new file mode 100644 index 0000000000..d56083987f --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/overview.md @@ -0,0 +1,38 @@ +--- +description: "Security Overview" +sidebar_label: "Overview" +slug: /advanced-and-troubleshooting/security/overview +--- + +# Overview + +This page serves as an overview of the Obol Network from a security point of view. + +This page is updated quarterly. The last update was on 2024-June-19. + +## Table of Contents + +* [Overview](overview.md) + * [Table of Contents](overview.md#table-of-contents) + * [List of Security Audits and Assessments](overview.md#list-of-security-audits-and-assessments) + * [Security focused documents](overview.md#security-focused-documents) + * [Bug Bounty](overview.md#bug-bounty) + +## List of Security Audits and Assessments + +The completed audits reports are linked [here](https://github.com/ObolNetwork/obol-security/tree/main/audits). + +* A review of Obol Labs [development processes](./ev-assessment.md) by [Ethereal Ventures](https://www.etherealventures.com/). +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/) resulting in version [`v0.16.0`](https://github.com/ObolNetwork/charon/releases/tag/v0.16.0). +* A second [assessment of Charon](https://obol.tech/charon_quantstamp_assessment.pdf) by [QuantStamp](https://quantstamp.com/) resulting in version [`v0.19.1`](https://github.com/ObolNetwork/charon/releases/tag/v0.19.1). +* A [solidity audit](./smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* A [penetration testing certificate](https://github.com/ObolNetwork/obol-security/blob/main/audits/Sayfer_2024-03_Penetration_Testing_CFD.pdf) of the Obol DV Launchpad by [Sayfer](https://sayfer.io/). +* A second [solidity audit](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V2%20Audit%20-%20Nethermind.pdf) by [Nethermind](https://nethermind.io). + +## Security focused documents + +* A [threat model](./threat_model.md) for a DV middleware client like Charon. + +## Bug Bounty + +Information related to disclosing bugs and vulnerabilities to Obol can be found on [the next page](bug-bounty.md). diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/risks.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/risks.md new file mode 100644 index 0000000000..46d2302a3d --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/risks.md @@ -0,0 +1,53 @@ +--- +description: "Outlining potential centralization risks and their mitigations" +sidebar_label: "Centralization Risks and Mitigation" +slug: /advanced-and-troubleshooting/security/risks +--- + +# Centralization Risks and Mitigation + +## Risk: Obol hosting the relay infrastructure + +**Mitigation**: Self-host a relay. + +One of the risks associated with Obol hosting the [LibP2P relays](../../learn/charon/charon-networking.md) infrastructure allowing peer discovery is that if Obol-hosted relays go down, peers won't be able to discover each other and perform the DKG. To mitigate this risk, external organizations and node operators can consider self-hosting a relay. This way, if Obol's relays go down, the clusters can still operate through other relays in the network. Ensure that all nodes in the cluster use the same relays, or they will not be able to find each other if they are connected to different relays. + +The following non-Obol entities run relays that you can consider adding to your cluster (you can have more than one per cluster, see the `--p2p-relays` flag of [`charon run`](../../learn/charon/charon-cli-reference.md#the-run-command)): + +| Entity | Relay URL | +| ------------------------------------------- | ------------------------------------ | +| [DSRV](https://www.dsrvlabs.com/) | https://charon-relay.dsrvlabs.dev | +| [Infstones](https://infstones.com/) | https://obol-relay.infstones.com/ | +| [Hashquark](https://www.hashquark.io/) | https://relay-2.prod-relay.721.land/ | +| [Figment](https://figment.io/) | https://relay-1.obol.figment.io/ | +| [Node Guardians](https://nodeguardians.io/) | https://obol-relay.nodeguardians.io/ | + +## Risk: Obol being able to update Charon code + +**Mitigation**: Pin specific docker versions or compile from source on a trusted commit. + +Another risk associated with Obol is the Labs team having the ability to update the [Charon code](https://github.com/ObolNetwork/charon) used by node operators within DV clusters, which could introduce vulnerabilities or malicious code. To mitigate this risk, operators can consider pinning specific versions or hashes of the Docker image or git repo commits that have been [thoroughly tested](overview.md#list-of-security-audits-and-assessments) and accepted by the network. This would ensure that any updates are carefully vetted and reviewed by the community, and only introduced into a running cluster gradually. The labs team will strive to communicate the security or operational impact any Charon update entails, giving operators the chance to decide whether they want potential performance or quality of experience improvements, or whether they remain on a trusted version for longer. + +## Risk: Obol hosting the DV Launchpad + +**Mitigation**: Use [`create cluster`](../../learn/charon/charon-cli-reference.md#the-create-command) or [`create dkg`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) locally and distribute the files manually. + +Hosting the first Charon frontend, the [DV Launchpad](../../learn/intro/launchpad.md), on a centralized server could create a single point of failure, as users would have to rely on Obol's server to access the protocol. This could limit the decentralization of the protocol and could make it vulnerable to attacks or downtime. Obol hosting the launchpad on a decentralized network, such as IPFS would be a first step but not enough. This is why the Charon code is source-available and contains a CLI interface to interact with the protocol locally. + +To mitigate the risk of launchpad failure, consider using the `create cluster` or `create dkg` commands locally and distributing the key shares files manually. + +## Risk: Obol custodying pre-signed exit messages + +**Mitigation**: Use withdrawal address initiated exits or validator client exits + +Before the Pectra hardfork, there was no way for a delegator to exit their validator without the co-operation of the node operator(s). In an effort to reduce this risk, Obol developed the [Charon exit](../../learn/charon/charon-cli-reference.md#the-exit-command) command, which allows operators to pre-sign and download exit messages to give to the delegator for safe keeping, ensuring they could broadcast them at any point in time. This feature relies on Obol's [API](../../api/what-is-this-api), and means the Obol core team could in theory initiate an unwanted exit. If a delegator does not want to be exposed to that centralization risk, they should not use Charon's built-in exit commands, and instead should initiate exits using the [EIP7002](https://eips.ethereum.org/EIPS/eip-7002) exit contract, or alternatively by running normal exit commands on the operator's validator clients. + +Guides to exiting validators using all three approaches are outlined [here](../../run-a-dv/running/exit-a-dv.mdx). + +## Risk: Obol going bust/rogue + +**Mitigation**: Use key recovery. + +The final centralization risk associated with Obol is the possibility of the company going bankrupt or acting maliciously, which could lead to a loss of confidence in the Charon client. To mitigate this risk, Obol has implemented a key reconstitution mechanism. This would allow the clusters to continue operating and to (re)create full validator private keys suitable for standard staking setups even if Obol is no longer able or willing to provide support. + +A guide to recombine key shares into a single private key can be accessed [here](../advanced/quickstart-combine.md). diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/smart-contract-audit.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/smart-contract-audit.md new file mode 100644 index 0000000000..c23023dd88 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/smart-contract-audit.md @@ -0,0 +1,467 @@ +--- +sidebar_label: "Smart Contract Audit" +slug: /advanced-and-troubleshooting/security/smart-contract-audit +--- + +# Smart Contract Audit + +## Obol Audit Report: Obol Manager Contracts + +Prepared by: Zach Obront, Independent Security Researcher + +Date: Sept 18 to 22, 2023 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2023%20-%20Obol%20Splits%20V1%20Audit%20-%20Zach%20Obront.pdf) + +### About **Obol**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-obol) {#about-obol} +The Obol Network is an ecosystem for trust minimized staking that enables people to create, test, run & co-ordinate distributed validators. + +The Obol Manager contracts are responsible for distributing validator rewards and withdrawals among the validator and node operators involved in a distributed validator. + +### About **zachobront**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-zachobront) {#about-zachobront} +Zach Obront is an independent smart contract security researcher. He serves as a Lead Senior Watson at Sherlock, a Security Researcher at Spearbit, and has identified multiple critical severity bugs in the wild, including in a Top 5 Protocol on Immunefi. You can say hi on Twitter at [@zachobront](http://twitter.com/zachobront). + +### Summary & Scope[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary--scope) {#summary--scope} +The [ObolNetwork/obol-manager-contracts](https://github.com/ObolNetwork/obol-manager-contracts/) repository was audited at commit [50ce277919723c80b96f6353fa8d1f8facda6e0e](https://github.com/ObolNetwork/obol-manager-contracts/tree/50ce277919723c80b96f6353fa8d1f8facda6e0e). + +The following contracts were in scope: + +* src/controllers/ImmutableSplitController.sol +* src/controllers/ImmutableSplitControllerFactory.sol +* src/lido/LidoSplit.sol +* src/lido/LidoSplitFactory.sol +* src/owr/OptimisticWithdrawalReceiver.sol +* src/owr/OptimisticWithdrawalReceiverFactory.sol + +After completion of the fixes, the [2f4f059bfd145f5f05d794948c918d65d222c3a9](https://github.com/ObolNetwork/obol-manager-contracts/tree/2f4f059bfd145f5f05d794948c918d65d222c3a9) commit was reviewed. After this review, the updated Lido fee share system in [PR #96](https://github.com/ObolNetwork/obol-manager-contracts/pull/96/files) (at commit [fd244a05f964617707b0a40ebb11b523bbd683b8](https://github.com/ObolNetwork/obol-splits/pull/96/commits/fd244a05f964617707b0a40ebb11b523bbd683b8)) was reviewed. + +### Summary of Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary-of-findings) {#summary-of-findings} +| Identifier | Title | Severity | Fixed | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------- | ----- | +| [M-01](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) | Future fees may be skirted by setting a non-ETH reward token | Medium | ✓ | +| [M-02](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) | Splits with 256 or more node operators will not be able to switch on fees | Medium | ✓ | +| [M-03](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) | In a mass slashing event, node operators are incentivized to get slashed | Medium | | +| [L-01](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) | Obol fees will be applied retroactively to all non-distributed funds in the Splitter | Low | ✓ | +| [L-02](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) | If OWR is used with rebase tokens and there's a negative rebase, principal can be lost | Low | ✓ | +| [L-03](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) | LidoSplit can receive ETH, which will be locked in contract | Low | ✓ | +| [L-04](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) | Upgrade to latest version of Solady to fix LibClone bug | Low | ✓ | +| [G-01](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) | stETH and wstETH addresses can be saved on implementation to save gas | Gas | ✓ | +| [G-02](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) | OWR can be simplified and save gas by not tracking distributedFunds | Gas | ✓ | +| [I-01](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) | Strong trust assumptions between validators and node operators | Informational | | +| [I-02](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) | Provide node operator checklist to validate setup | Informational | | + +### Detailed Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#detailed-findings) {#detailed-findings} +#### \[M-01] Future fees may be skirted by setting a non-ETH reward token[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) {#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token} +Fees are planned to be implemented on the `rewardRecipient` splitter by updating to a new fee structure using the `ImmutableSplitController`. + +It is assumed that all rewards will flow through the splitter, because (a) all distributed rewards less than 16 ETH are sent to the `rewardRecipient`, and (b) even if a team waited for rewards to be greater than 16 ETH, rewards sent to the `principalRecipient` are capped at the `amountOfPrincipalStake`. + +This creates a fairly strong guarantee that reward funds will flow to the `rewardRecipient`. Even if a user were to set their `amountOfPrincipalStake` high enough that the `principalRecipient` could receive unlimited funds, the Obol team could call `distributeFunds()` when the balance got near 16 ETH to ensure fees were paid. + +However, if the user selects a non-ETH token, all ETH will be withdrawable only thorugh the `recoverFunds()` function. If they set up a split with their node operators as their `recoveryAddress`, all funds will be withdrawable via `recoverFunds()` without ever touching the `rewardRecipient` or paying a fee. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation) + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept) + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-1) + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-1) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendations) + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-2) + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-2) + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-3) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-3) + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-4) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-1) + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-4) + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-5) + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-2) + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-5) + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-6) + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-6) + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-7) + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-7) + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-8) + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-9) + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-10) + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\ diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..1e557a58a5 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,155 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritise the liveness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalise operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator. A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..1ed84c4d89 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# troubleshooting + diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..5b713ecb62 --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,298 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting any other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +For now, ENR rotation/replacement is not supported, it will be supported in a future release. Therefore, it's advised to always keep a backup of your `charon-enr-private-key ` in a secure location (ex: cloud storage, USB Flash drive, etc.). + +### I can't find the keys anywhere +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows. +Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + + +## Lighthouse + + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + + +### Lighthouse gives the error `not enough time for a discovery search` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance. +Using 3rd-party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Can't connect to Beacon API` + +If you are running EL and CL outside Obol on the same machine, you might need to open ports in your firewall to allow connections incoming from the docker instance. +In order to know the IP of the docker network, run: +`docker network inspect ` + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is +probably not online to sign successfully. Make sure all operators are +running the latest version of Charon. To check if some peers are not online: +`docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key +should be created and placed in the right directory during the ceremony. +Also, make sure you are working in the right directory: +`charon-distributed-validator-node`. + +### `Failed to confirm node connection` +Wait for Teku & Lighthouse sync to be complete. + + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum +limit has been reached. This is most often due to "maximum reservations per IP/peer". +This is when your Charon node is restarting or in some error loop and constantly +attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it. +This should allow the relay enough time to reset your IP/peer limits and +should then allow new reservations. This could also be due to the relay +being overloaded in general, so reaching a server wide "maximum connections" +limit. This is an issue with relay scalability and we are working in a long +term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO_RESERVATION (204)` indicates the peer +isn't connected to the relay, so the the Charon client cannot connect to the +peer via the relay. That might be because the peer is offline or the peer is +configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact +same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when +it failed to fetch the required data from the beacon node API. This indicates +a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +attestation data. This indicates the associated attestation duty failed to obtain +a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed due to no partial v2 committee subscription submitted by the cluster +validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to insufficient +partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to no partial randao +signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This +could indicate that insufficient honest peers participated in consensus or p2p +network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted +by the local validator client. This could indicate that the local validator client +is offline, or has connection problems with Charon, or has some other problem. +See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database +as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was +received from any peer. This indicates all peers are offline or p2p network connection +problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures +for the duty was received from peers. This indicates problems with peers or p2p +network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient +partial signatures failed. This indicates inconsistent signed data. This indicates +a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it +checks for a special file called the private key lock file. This file has the +same name as the ENR private key file but with a `.lock` extension. +If the private key lock file exists and is not older than 5 seconds, Charon won't +run. It doesn't allow running multiple Charon instances with the same ENR private +key. If the private key lock file has a timestamp older than 5 seconds, Charon +will replace it and continue with its work. If you`re sure that no other Charon +instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the +validators private key shares don't match the ENR private key. There may +have been a mix-up during deployment, leading to a mismatching validator +client key share index. + +For example: Imagine node N is Alice, and node M is Bob, the error would read: +` mismatching validator client key share index, Bob's key share submitted to Alice's charon node ` +Bob's private key share(s) are imported to a VC that is connected to +Alice's Charon node. This is an invalid setup/deployment. +Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside +cluster-lock.json and see that matches with the public key inside +`node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data the first time. +You can solve this by following the steps below: +- Click the Wheel Icon > Datasources. +- Click prometheus. +- Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +- Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel +Can be linked to a Teku keystore issue. + + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + You can ignore this error unless you have been contacted by the Obol Team + with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. + + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly +on Linux and WSL for Windows systems. In the interest of security, the +charon docker image runs as a non-root user, and this user often does not +have the permissions to write in the directory you have checked out the code +to. This can be generally be fixed with some of the following: +- Running docker commands with `sudo`, if you haven't [set up docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +- Changing the permissions of the `.charon` folder with the commands: + - `mkdir .charon` (if it doesn't already exist); + - `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + It`s because both Nethermind and Lighthouse start syncing and so there's + connectivity issues among the containers. Simply let the containers run for + a while. You won't observe frequent errors when Nethermind finishes syncing. You + can also add a second beacon node endpoint for something like Infura by + adding a comma separated API URL to the end of + `CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. + +### How do I fix the `plugin "loki" not found` error? + If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + + +## Relay + +### ` Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the +relay/docker-compose.yml with your real public IP or DNS hostname. + +### ` Timeout resolving bootnode ENR: context deadline exceeded` +The relay you are trying to connect to your peers via is offline or +unreachable. + diff --git a/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..83d3f55c5e --- /dev/null +++ b/versioned_docs/version-v1.6/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or uncontactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.6/api/address.mdx b/versioned_docs/version-v1.6/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.6/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.6/api/cluster-definition.mdx b/versioned_docs/version-v1.6/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.6/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.6/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.6/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..4da8ad1bcc --- /dev/null +++ b/versioned_docs/version-v1.6/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Effectiveness + + diff --git a/versioned_docs/version-v1.6/api/cluster-lock.mdx b/versioned_docs/version-v1.6/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.6/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.6/api/dv-exit.mdx b/versioned_docs/version-v1.6/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.6/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.6/api/metrics.mdx b/versioned_docs/version-v1.6/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.6/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.6/api/owr-information.mdx b/versioned_docs/version-v1.6/api/owr-information.mdx new file mode 100644 index 0000000000..0e20b4892a --- /dev/null +++ b/versioned_docs/version-v1.6/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR + + diff --git a/versioned_docs/version-v1.6/api/state.mdx b/versioned_docs/version-v1.6/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.6/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.6/api/system.mdx b/versioned_docs/version-v1.6/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.6/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.6/api/techne-credentials.mdx b/versioned_docs/version-v1.6/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.6/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.6/api/terms-and-conditions.mdx b/versioned_docs/version-v1.6/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..d5d32a5dba --- /dev/null +++ b/versioned_docs/version-v1.6/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TermsAndConditions + + + + diff --git a/versioned_docs/version-v1.6/api/what-is-this-api.md b/versioned_docs/version-v1.6/api/what-is-this-api.md new file mode 100644 index 0000000000..6951dbffbb --- /dev/null +++ b/versioned_docs/version-v1.6/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://launchpad.obol.org), a dApp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API can also be used via the [Obol-SDK](../sdk/index.md). + +Read more about Obol and how to use the [launchpad](https://launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.6/community-and-governance/community/README.md b/versioned_docs/version-v1.6/community-and-governance/community/README.md new file mode 100644 index 0000000000..c8d5f1c1b9 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# community + diff --git a/versioned_docs/version-v1.6/community-and-governance/community/grants-program/README.md b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/README.md new file mode 100644 index 0000000000..9e63a519eb --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/README.md @@ -0,0 +1,72 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/community/grants-program +--- + +# Grants Program + +We are excited to launch the **Obol Grants Program**. After a successful pilot wave that supported several meaningful initiatives, we’re doubling down on our commitment to ecosystem growth. + +If you're curious about what we funded in the past, check out our [Grants Pilot Wrap-Up blog post](https://blog.obol.org/grants-program-pilot-wave-report-pilot-phase-wrap-up/). It includes full context and direct links to our Questbook portal where you can browse the funded projects and on-chain disbursement records. + +*** + +## Purpose + +The Obol Grants Program supports projects that advance the strategic goals of the Obol. The goal is to: + +* Provide milestone-based funding to **builders** aligned with our goals +* Offer a standardized and permissionless framework for **educators and event organizers** to run impactful Obol-focused community events & workshops +* Enable technical contributors to pick up **open-source missions** from our backlog + +This program exists to extend the reach of the Collective: helping us ship faster, strengthen adoption of Distributed Validators (DVs), other important Obol technology, and empower contributors globally. + +## Structure + +The Grants Program is organized into **three distinct Grant Tracks:** + +### [Staking Mastery Program](grants-track-for-staking-masters.md) + +* For contributors applying to work on any of the [Obol Collective 2025 SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388) +* This track revives the original Staking Mastery Program. I will now be running on a rolling basis to support research and technical contributions that advance distributed staking +* Open application process with milestone-based disbursement + +### [Community Events & Workshops](grants-track-for-community-events.md) + +* For anyone hosting Obol-focused workshops, meetups or onboarding sessions +* Permissionless structure, funded retroactively based on proof of attendance and impact + +### [Open Strategic Missions](grants-track-for-open-strategic-missions/strategic-open-missions.md) + +* Pre-scoped, technical tasks created by Obol +* Contributors can apply to complete these missions for funding + +:::danger +Before applying, make sure to check the detailed sub-page for each grant track by clicking on its title above. These pages outline specific requirements, proof formats, and payout logic for each track. +::: + +## Review Timeline + +All submitted applications (regardless of track) will receive an initial response within **7 business days**, with one of the following statuses: + +* ✅ **Accepted** — You’re good to start +* ❌ **Declined** — Not aligned with our current priorities +* 💬 **Needs Discussion** — We’d like to refine scope, budget, or timeline with you + +## Funding & Disbursement + +* All budgets are discussed in **USD** terms +* Disbursements are made in **OBOL tokens**, calculated at the time of milestone approval or delivery +* Payments can be **one-shot** or broken into **milestones**, depending on scope + +## Transparency & Communication + +* Every funded grant will be published publicly on **Questbook along with the detailed milestones and on-chain funding transactions.** You can find links to the relevant Questbook pages for each grant track in their dedicated sub-pages. +* Projects will be highlighted periodically through: +* Obol’s official social channels (Twitter, Discord) +* Grant recap blog posts & newsletters +* Grantees may be asked to publish short public recaps for visibility + +_**Ready to get started? You can learn more about each track by visiting the dedicated pages.**_ + +\ diff --git a/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-community-events.md b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-community-events.md new file mode 100644 index 0000000000..3b17b4f6ab --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-community-events.md @@ -0,0 +1,135 @@ +--- +sidebar_label: "Grants Track for Community Events" +slug: /community-and-governance/community/grants-program/grants-track-for-community-events +--- + +# Grants Track for Community Events + +This track supports permissionless, retroactive funding for Obol-focused local events, workshops, and onboarding sessions focused on Distributed Validators. + +The goal is to empower community leaders to grow Obol on the ground, with a clear and standardized support model. + +You can explore all supported events on [Questbook](https://questbook.app/dashboard/?grantId=68d793dd306fa3a0a64b83c2\&chainId=10). + +*** + +## Overview, Eligibility and Scope + +This track is designed to support **community-led educational events and workshops** that are **entirely focused on Obol Distributed Validators (DVs)**. These events should serve to onboard new participants, educate existing ones, and help expand the reach of Obol on the ground. + +To ensure consistency and predictability, this track uses a **permissionless framework** for supporting events with **up to 100 attendees.** Larger events may still be supported, but require prior coordination. + +Funding is available for two types of outcomes: + +1. **The event itself** — covering costs related to the event venue, food and beverages. +2. S**uccessful conversions to Obol DVs** — when attendees go on to spin up Distributed Validators using Obol technology, the event host or operators may qualify for a bonus reward. + +All events must: + +* Be **fully centered on Obol DVs** +* Be **submitted with the required proofs** to unlock retroactive funding upon verification +* Be limited to **100 participants or fewer** for automatic eligibility + +## Budget & Funding + +### 🍕 1. Food & Drink Budget (Event Support) + +To help cover the costs of hosting, we provide **up to $15 per verified attendee**, retroactively, upon proof of the event. This amount includes the event venue, food, drinks, and minor operational expenses. + +* This support is **capped at 100 attendees per event.** +* Verification requirements are listed in the next section (“Submission Process”). + +### 🧪 2. TVS Conversion Bonus (Net New Stake Incentive) + +To reward tangible ecosystem growth, we offer a **0.1% bonus of the total net new TVS (Total Value Staked)** attributable to your event. + +* Only **Obol-based DV clusters** are eligible. +* The **conversion must clearly follow from the event**, with proof submitted and verified. +* Bonus payouts will be made **monthly** over a **12-month period**, so long as the validators remain active. + +:::tip +For example, if your event led to the launch of 5 validators totaling 160 ETH (≈$640K TVS with ETH at $4000), you could be eligible for a $640 bonus, distributed over 12 months (\~$53.33/month), assuming validators remain online and performing. +::: + +This structure is designed to: + +* Ensure **sustainable staking growth**, not just one-time deposits +* Protect against potential **farming or gaming** of the bonus system +* Reward contributors for **long-term value creation** in the network + +:::danger +All budgets will be denominated in USD for clarity, and payments will be made in OBOL token equivalents at the time of disbursement. +::: + +:::tip +Want to estimate your potential TVS Conversion Bonus? Use this [simulator](https://bonus.gcp.obol.tech/) to adjust the ETH price and number of validators and preview your expected monthly rewards. +::: + +_The TVS conversion bonus will be paid directly to the operator who submits the form and verifies their validator address. It is then up to them to decide if or how they wish to share this bonus with the event organizer or other contributors. The Obol Association reserves the right to modify the bonus structure or reward calculation method at any time for future submissions. Any bonuses already approved and in-progress will remain unchanged and honored as agreed._ + +## Submission Process + +The Community Events track uses a simple **three-step submission flow**. Only one of them is optional, the rest are required for funding. + +### 1. [Pre-Event Form (optional but recommended)](https://forms.gle/Y5LTpEkF3TThRNUo9) + +We encourage hosts to fill out a short form **ahead of their event** to let the Association know what’s being planned. While not mandatory, this step allows us to: + +* Coordinate on visibility and cross-post the event on official channels +* Offer lightweight guidance or connections if needed +* Ensure the event fits within the scope of this grant track + +### 2. [Post-Event Submission (required for pizza & food budget)](https://forms.gle/MRZEaX3DtSZe9jSK7) + +After the event, hosts must fill out a **proof-of-event** form to unlock retroactive funding. This submission must include: + +* A **public tweet thread** summarizing the event\ + ↳ Must highlight Obol DVs and mention @ObolCollective +* A **group photo** from the event, with clear timestamp and the organizer present +* Any **slides or presentation materials** used during the event +* A link to the **Luma page (or equivalent)** used for RSVPs\ + ↳ Must include attendee list +* **Receipts** (food/beverage/venue) matching the number of participants + +_**Once submitted, your application will be reviewed and — if approved — disburse the food & drink budget (up to $15/attendee, max 100 attendees).**_ + +### 3. [TVS Conversion Bonus Submission (required for validator conversion bonus)](https://forms.gle/cmz5uw6cCwM5pZi96) + +There’s no deadline here, submit any time after the event once validators are live. To unlock your **TVS Conversion Bonus**, we require to fill the dedicated form with: + +* A submission from one of the **validator operators**, including: + * **Ethereum address** used to run the validator (to prove ownership) + * **Details of the Distributed Validator cluster** (to verify it was launched post-event) + * **Statement of correlation** explaining how the event led to this onboarding +* Follow-up confirmation from the **event organizer** +* A **public recap** from the host listing the validators or clusters onboarded via the event + +_**Once submitted, your application will be reviewed and — if approved — we will distribute the TVS bonus (0.1% of net new TVS distributed over 12 months).**_ + +## Evaluation & Review + +For **each of the three forms submitted** (pre-event intent, post-event proof, or TVS conversion bonus), Obol will respond within **seven open business days** with one of the following: + +* ✅ **Accepted** +* ❌ **Rejected** +* 💬 **Needs additional information** + +Once post-event materials have been reviewed and accepted, the host will be asked to **submit the final version of the application to Questbook**, including: + +* A summary of the event +* Final verified participant count +* Funding amount (e.g. food & drink budget) + +This Questbook submission will serve as the **source of truth for transparency and on-chain funding**. + +:::tip +If a validator conversion bonus is approved at a later date, it will be logged as a second milestone under the same Questbook grant and funded accordingly. +::: + +## Expectations & Visibility + +We want to **showcase and amplify** meaningful contributions from the community. + +* If the event was flagged in advance via the optional pre-event form, we may help promote it via **Obol's official social media channels**, including social media and/or Discord. +* Once an event has been successfully validated and funded, it will be included in **periodic blog posts or funding recap threads.** +* We strongly encourage hosts to post their own event recaps publicly on X (Twitter) and **tag @ObolCollective** to boost visibility of their work and highlight the role of DVs in the broader staking ecosystem. diff --git a/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md new file mode 100644 index 0000000000..602d43c8d5 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md @@ -0,0 +1,79 @@ +--- +sidebar_label: "Grants Track for Open Strategic Missions" +slug: /community-and-governance/community/grants-program/grants-track-for-open-strategic-missions +--- + +# Grants Track for Open Strategic Missions + +This track enables technical contributors to pick up pre-scoped missions designed by the Obol team. + +These missions are ideal for developers looking to ship meaningful tooling or infrastructure improvements for the DV ecosystem. + +To view active and completed missions, visit [Questbook](https://questbook.app/dashboard/?grantId=68d79449306fa3a0a64b88e9\&chainId=10). + +*** + +## Overview, Eligibility and Scope + +This track enables technical contributors to pick up **pre-scoped missions** designed by the Obol team. + +These missions are ideal for developers looking to ship meaningful tooling, research, or infrastructure improvements for **Obol Distributed Validators.** + +These missions are published directly in the [section below](strategic-open-missions.md). Each mission outlines: + +* The scope of work +* The deliverables expected +* The funding offered +* Context and materials + +This track is open to: + +* Independent developers and small technical teams +* Individuals with proven experience in Ethereum staking, especially Distributed Validators + +Our goal is to reduce internal backlog by collaborating with technically proficient external contributors who want to build meaningful tooling, integrations, or research for the Obol ecosystem. + +## Budget & Funding + +Each mission comes with a proposed **budget offer.** These grants follow a **milestone-based payment** model: + +* Milestones are defined up front as part of the mission spec or during onboarding +* Funding is disbursed **only after milestone completion is validated** + +If adjustments are needed to the scope or funding, these will be clarified before the contributor starts work. + +## Submission Process + +Anyone interested in picking up a mission must fill out a [short application form](https://forms.gle/SgUx4n7hAZ28JpY47). It will request: + +* Name of the mission +* Background and relevant experience of the applicant(s) +* Relevant GitHub links or previous work +* Optional: Questions or additional clarification requests + +Only after submitting this form and receiving explicit approval may a contributor begin work. + +## Evaluation & Review + +Once an application form is submitted, Obol will provide a first response within **seven open business days**, which will be one of the following: + +1. ✅ **Accepted**: The contributor is cleared to begin work +2. ❌ **Rejected**: The contributor is not a fit or the mission is already taken +3. 💬 **Further discussion required**: Additional alignment on scope, timeline, or budget is needed + +:::danger +If you begin work without approval, we reserve the right to decline funding even if the work is completed. +::: + +## Expectations & Visibility + +Contributors to this grant track will be expected to: + +* Provide milestone updates or completion summaries +* Be open to publishing public recaps or demos + +In return, Obol will: + +* Highlight completed missions on social channels +* Include them in quarterly reports and blog posts +* Provide visibility to help contributors build reputation diff --git a/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md new file mode 100644 index 0000000000..8d2c99f75b --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md @@ -0,0 +1,85 @@ +--- +sidebar_label: "Strategic Open Missions" +slug: /community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions +--- + +# Strategic Open Missions + +To view ongoing and completed missions, visit [Questbook](https://questbook.app/dashboard/?grantId=68d79449306fa3a0a64b88e9\&chainId=10). + +This section will serve as the **central hub** for all currently available open missions under the Staking Mastery Program. + +* It will be updated regularly with new missions +* Completed missions will be archived +* Funded missions will be trackable via our Questbook hub + +Please check back soon for available missions. + +If you have a technical mission you'd like to propose to Obol instead, please use the [Staking Masters Grants track](../grants-track-for-staking-masters.md). + +*** + +## Open Strategic Missions + +This section lists specific, high-impact technical initiatives Obol has decided to open to external contributors. These are projects that contribute meaningfully to the Obol Distributed Validators (DVs) and we welcome applications from individuals or teams with the right expertise. + +Each mission includes a pre-defined scope and fixed budget. All applications are reviewed on a case-by-case basis. + +:::danger +All Open Missions must go through the official application and evaluation process before work begins. Milestone-based funding is tracked via Questbook and paid upon approval. +::: + +## 🟢 Open for Application + +### Add Validator Feature in DappNode + +**Goal**: Implement the add-validator functionality into the Obol DappNode package, leveraging the existing docs as reference. + +🔗[ docs.obol.org/add-validators](https://docs.obol.org/advanced-and-troubleshooting/advanced/add-validators) + +**Background**: This feature would allow users to dynamically add validators post-launch via DappNode. It is not currently supported and would require someone familiar with the Obol DappNode integration layer. + +**Expected Deliverables:** + +* Integrate add-validator logic into DappNode package +* Ensure compatibility with Charon +* Include light documentation and testing instructions + +**Budget**: \~$1,000 USD + +**Funding**: Milestone-based, paid in $OBOL equivalent + +## 🟠 In Progress + +### TEEs for DVT Security (Sebastian Faust, PolyCrypt GmbH) + +**Goal**: Prototype and benchmark how Trusted Execution Environments (Intel TDX) can secure DV operations. + +**Expected Deliverables:** + +* Run a DVT node (Charon + VC) inside Intel TDX +* Benchmark performance and risk mitigation +* Produce documentation, open-source code, and in-depth report + +**Funding**: $10,000 in stables + $10,000 in $OBOL + +**Status**: Started (September 2025) + +### Ansible Playbooks for Obol DVT (Jeremiah Sullivan) + +**Goal**: Build automated Ansible roles for DVT cluster deployment and home staking setups. + +**Scope**: + +* Docker Images with CI/CD for DVT components +* Ansible Roles for Charon deployment and validator configuration +* Monitoring setup with Grafana dashboards and webhook alerts +* Step-by-step documentation + +**Funding**: 7,000 $OBOL + +**Milestones**: Final delivery expected Q4 2025 + +**Status**: Ongoing (public GitHub in progress) + +\ diff --git a/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-staking-masters.md b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-staking-masters.md new file mode 100644 index 0000000000..ed4041f9d8 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/grants-program/grants-track-for-staking-masters.md @@ -0,0 +1,90 @@ +--- +sidebar_label: "Grants Track for Staking Masters" +slug: /community-and-governance/community/grants-program/grants-track-for-staking-masters +--- + +# Grants Track for Staking Masters + +This track covers proposals aligned with the [Collective’s SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388). + +It is designed for Staking Masters who want to proactively work on strategic initiatives that support Obol’s mission. + +You can browse funded grants and milestone details for this track on[ ](https://questbook.app/grants/obol/track-name-placeholder)[Questbook](https://questbook.app/dashboard/?grantId=68d792a86fd5365ca2538329\&chainId=10). + +*** + +## Overview, Eligibility and Scope + +The **Staking Mastery Program** is a rolling grant track designed to empower individual contributors and small technical teams working to advance distributed staking. This track revives the ethos of the original [Staking Mastery Cohorts](../staking-masters.md) by preserving their spirit of excellence, but adapts the structure to support proactive applications aligned with the [Obol Collective’s 2025 SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388). + +Unlike the original cohort-based model, this new iteration operates on a rolling basis. Contributors can apply at any time to work on initiatives that push forward distributed validator adoption, improve technical general infrastructure, or deliver impactful research. The focus here is technical. One time education initiatives are supported separately through our [Community Events track](grants-track-for-community-events.md). + +This grant track is designed for proactive applications submitted by individual contributors or small teams interested in helping the Collective move forward. These can include topics such as: + +* Deepening DV penetration in staking and restaking protocols +* Expanding DV accessibility through tooling or automation +* Improving infrastructure compatibility with Obol DVs +* Conducting meaningful research in distributed validator technologies +* Integrating Defi protocols or adding more utility to the token + + + +**To be eligible, applications must:** + +* Be aligned with the 2025 SQUAD Goals of the Obol Collective +* Propose realistic deliverables that advance distributed staking +* Be led by individuals or small teams with proven technical expertise in staking, governance, infrastructure, or Ethereum protocols + +There is no fixed format or size constraint for proposals. We welcome both small- and large-scope projects but they should be concrete, measurable, and narratively clear. + +## Budget & Funding + +Applicants must request funding using the template included in the application form. All budgets should be **denominated in USD** for clarity, and payments will be made in **OBOL token equivalents** at the time of disbursement. + +Grants are **milestone-based**. This means: + +* Funding is **not disbursed upfront**. +* Each milestone must be **completed and approved** before the associated funding is released. +* Once a milestone is validated, the grantee can move on to the next phase and receive subsequent funding. + +## Submission Process + +There is no deadline or wave. Applications are accepted on a **rolling basis**. + +To apply, simply [fill out the dedicated application form](https://forms.gle/hJfXtGZFZqNoWAyE8), which includes sections for: + +* An overview of your project and its alignment with the Collective’s SQUAD Goals +* A breakdown of proposed milestones and deliverables +* Team background and relevant experience +* A detailed cost breakdown and requested budget (USD-denominated) + +## Evaluation & Review + +Once a submission is received, applicants can expect an **initial triage within 7 business days**. This first response will fall into one of three categories: + +1. ✅ **Accepted** — you’re good to move forward as-is. +2. ❌ **Rejected** — the proposal is not aligned or not feasible at this time. +3. 💬 **Discussion Required** — we’re interested, but need further alignment on scope, milestones, or budget. + +In most cases, we anticipate some **back-and-forth discussion** to refine the proposal before final approval. + +Once aligned, applicants will be asked to **submit the final version** of the grant to Questbook, including: + +* Project overview +* Final milestones +* Approved budget + +Questbook will serve as the **source of truth** for the proposal and allow anyone to **track the funding on-chain.** + +## Expectations & Visibility + +We want to showcase the valuable work being built across the ecosystem. + +Upon completion of significant milestones (or the full project), we’ll highlight the grant publicly via: + +* Obol’s social channels +* Periodic blog posts or newsletters summarizing recent grants + +We also encourage grantees to share their own updates publicly, to **build visibility** for both their work and the broader Collective. + +\ diff --git a/versioned_docs/version-v1.6/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.6/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..e88964cd95 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/staking-masters.md @@ -0,0 +1,27 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program (Archived)" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\\ + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.6/community-and-governance/community/techne.md b/versioned_docs/version-v1.6/community-and-governance/community/techne.md new file mode 100644 index 0000000000..f7897a2455 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/community/techne.md @@ -0,0 +1,120 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\\ + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::info +For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. +::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.obol.org) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.obol.org) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.obol.org) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.6/community-and-governance/contribution/README.md b/versioned_docs/version-v1.6/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..5cff17667a --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# contribution + diff --git a/versioned_docs/version-v1.6/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.6/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +```markdown + ```javascript + console.log(error); + ``` +``` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.6/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.6/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e17d6226af --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +- Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +- Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/README.md b/versioned_docs/version-v1.6/community-and-governance/governance/README.md new file mode 100644 index 0000000000..5f7a5f88c0 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/README.md @@ -0,0 +1,58 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# Governance + +The Obol Collective is building a decentralized governance system rooted in the core values of Web3: transparency, openness, collaboration, and community-led decision making. At the same time, we recognize that decentralization is a journey, not a switch. Our aim is to progressively decentralize Obol governance in a way that is sustainable, resilient, and free of the common pitfalls that have emerged in the ecosystem. + +## Our Vision: Pragmatic Decentralization + +We are here to stay. And we believe the only way to build a resilient and successful decentralized collective is to start by building a strong foundation. In recent months, many leading DAOs have experienced operational bottlenecks, inefficiency, and growing pains from decentralizing too fast, too early. The result? Several are now walking back toward more centralized structures to regain coordination capacity, accountability, and operational agility. + +We’ve learned from these examples. Our approach is different: we are deliberately not rushing into maximal decentralization. Instead, we are laying the groundwork for progressive, sustainable decentralization over time. + +At this stage of the Collective, execution matters. Proposals are already going through governance processes, but the Obol Association still holds executional authority to move quickly where needed. We see this as a temporary and necessary condition to keep building and shipping. This balance, transparent governance with accountable execution, is critical to avoid decision paralysis. + +Governance at Obol is not about decentralization for its own sake. It is about enabling the best decisions for the long-term health of the network. As emphasized in the [Bell Curve governance roundtable](https://youtu.be/vF8XuRuZs9g?si=0dw3uh8gLXyvFlUH), decentralization without shared purpose or coordination leads to deadlock. We aim to build a governance model that supports rather than hinders progress. + +## Inspiration + +We draw inspiration from both the successes and challenges of other DAOs. In particular: + +* [**Arbitrum DAO**](https://forum.arbitrum.foundation/t/a-vision-for-the-future-of-arbitrum/28962), Introduced “Arbitrum Aligned Entities” to fix governance gridlock by assigning execution to focused teams, while keeping strategic control with the DAO. A response to over-decentralizing too quickly and losing operational clarity. +* [**Compound**](https://www.comp.xyz/t/proposal-to-create-the-compound-foundation/6777?utm_source=substack\&utm_medium=email), Proposed the Compound Foundation to help the DAO coordinate services, manage treasury execution, and maintain continuity — moving from pure DAO toward a hybrid model with accountable support. + +These initiatives reinforce our belief that progressive decentralization, aligned with clear domain ownership and accountable entities, leads to more sustainable governance. + +## Principles We Follow + +* **Decentralization is a means, not an end.** Governance exists to serve the network, not to complicate it. +* **Stakeholders should govern what they understand.** Validators and technical contributors guide protocol upgrades; token holders lead incentive and treasury decisions. +* **Social consensus is paramount.** On-chain votes matter, but upgrades only succeed through real-world coordination and adoption. +* **Structures must evolve with the protocol.** Governance at genesis won’t look like governance at maturity. We are building toward that future in deliberate steps. + +## Governance Tools + +To support transparent decision-making and empower active participation, here are key tools used across the Collective: + +* [**Governance Forum**](https://community.obol.org/) – for proposal discussion and coordination +* [**Voting Portal**](https://vote.obol.org/) – to delegate or vote on proposals +* [**Dune Dashboard**](https://dune.com/vistalabs/obol-governance?ref=blog.obol.org) – to track voting data and delegate participation +* [**Staking Portal**](https://stake.obol.org/) – to stake OBOL and receive stOBOL +* [**0xretro.xyz**](https://0xretro.xyz/) – to access key info and metrics about delegates +* [**Cura Labs Dashboard**](https://obol.curiahub.xyz/delegate) – to find detailed insights on delegate reputation scores and contributions + +## Governance Sections + +The Obol governance documentation is organized into the following sections: + +* [collective.md](collective.md "mention") – framing the governance bodies, roles, and progressive decentralization pathway +* [token-house.md](token-house.md "mention") – the token-holder-based decision-making layer of the Collective +* [raf](raf/README.md "mention") – information for delegates participating in the Retroactive Funding Program (RAF) +* [grants-program](../community/grants-program/README.md "mention") – the Obol funding mechanism for contributors and ecosystem support, led by the Obol Association + +_These sections evolve as the governance process matures. For any feedback, ideas, or questions, we invite you to join the discussion on the_ [_Forum_](https://community.obol.org/) _or reach out via_ [_Discord_](https://discord.obol.org)_._ + +**Together, we are building governance for the long term.** diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/collective.md b/versioned_docs/version-v1.6/community-and-governance/governance/collective.md new file mode 100644 index 0000000000..4b93a757a8 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/collective.md @@ -0,0 +1,62 @@ +--- +description: "Obol Collective Overview" +sidebar_label: "Collective Overview" +slug: /community-and-governance/governance/collective +--- + +# Collective Overview + +## Purpose + +The Obol Collective’s governance system has two primary goals: + +1. **Resource allocation.** Allocate resources effectively to support the Collective’s vision and grow the Obol Collective's sustainable value. Long-term vision may sometimes conflict with short-term value creation; thus, governance requires a blend of short-term and long-term thinking to allocate the token treasury and protocol revenue effectively. +2. **Capture resistance.** Governance plays a key role in securing the anti-capture and censorship resistance of the Obol Collective. Governance should: + 1. make it possible for operations to continue over the long term without reliance on any individual entity; + 2. prevent any one entity or small group of entities from being able to control or censor. + +## Overview: The Obol Token House and RAF + +Two houses govern the Obol Collective: the Token House and the Obol RAF. + +In the **Token House,** OBOL Token holders are responsible for submitting, deliberating, and voting on governance proposals using the Governance Portal. Token holders can delegate their OBOL Token voting power to their own address or an eligible third party. Addresses with delegated voting power are called “Delegates”. + +In the **Obol Retroactive Fund (RAF)**, OBOL Token Delegates are responsible for allocating funds within the RAF to projects and teams that provide value to the Obol Collective. + +All OBOL holders and Delegates are expected to exercise their authority responsibly and follow the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. + +![](/img/gitbook/image-51.png) + +## The Security Council + +The Security Council is a committee of multi-sig wallet signers with the power to perform certain emergency actions as delegated to it by the Obol Association. + +The Security Council can execute any software upgrade or perform other emergency actions without delay to respond to a security emergency, should one arise. The Security Council must not use its power to perform Emergency Actions except in a true security emergency, such as a critical vulnerability that could significantly compromise the Obol Collective. + +After taking any Emergency Action, the Security Council must issue a full transparency report (at an appropriate time after the security emergency has passed) explaining what was done and why such action was justified. + +## Administration and Implementation + +In all cases, Obol Collective governance is intended to be carried out in a manner consistent with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. The Obol Association will steward this process as described below, with the goal of increasingly decentralising its role over time. + +The Obol Association, via its governance administrators, will facilitate administration to ensure that anyone may participate thoughtfully in governance. Such administrative services may include: + +* Moderation of governance proposals to ensure they are validly submitted and voted upon; +* Removal of proposals that reasonably appear to be fraudulent, spam-oriented, defamatory, hateful, or otherwise inappropriate or inconsistent with the values of the Collective; +* Monitoring of votes, voting power, the votable token supply, and voting periods for purposes of determining whether quorums and approval thresholds are met or accurately reflected; +* Management of mutually contradictory or duplicate proposals that are submitted simultaneously or close to one another; +* Maintenance of the Governance & RAF Portal; +* Other tasks that the Obol Association deems appropriate in connection with the above. + +The Association may also intervene operationally when necessary to uphold the integrity of the governance process — for instance, by removing improperly submitted proposals or enforcing community-agreed rules. When doing so, it will always act transparently and share justifications with the community. + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal or chosen RAF recipients, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails, coupled with an explanation. + +## Vision for Fully On-Chain Governance + +Once Collective’s governance develops and is deemed as sufficiently mature by the Obol Association, the implementations of passed proposals will follow full on-chain execution, where possible. Instead of the Collective’s reliance on the Obol Association for implementation, passed proposals will be moved to a queue to prepare for execution. The queue action will send the proposal to a Timelock contract, which starts a countdown until the proposal can be executed. + +Executing a proposal will run its function calls on-chain. Each proposal can be associated with one or more function calls. These calls will perform actions such as transferring assets from the treasury, updating the Governor's parameters, or calling another smart contract. diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/delegate-guide.md b/versioned_docs/version-v1.6/community-and-governance/governance/delegate-guide.md new file mode 100644 index 0000000000..5071ec9d15 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/delegate-guide.md @@ -0,0 +1,33 @@ +--- +description: "Delegate Guide" +sidebar_label: "Delegate Guide" +slug: /community-and-governance/governance/delegate-guide +--- + +# Delegate Guide + +## Delegate Rules of Engagement + +This document outlines the expectations, responsibilities, and values that should guide interactions within the Obol Collective governance community, including the Obol Forum, Discord, and working group meetings. This Code of Conduct will be reviewed periodically to incorporate feedback and adapt to governance needs. Any changes require community approval through the governance process. + +Please review these principles carefully to ensure alignment with the Obol Collective’s vision and commitment to a decentralized and sustainable ecosystem. + +Please read the rules of engagement on the forum [here](https://community.obol.org/t/delegates-rules-of-engagement/206). + +## **Governance Toolkit** + +These tools or their uses may change over time as governance evolves. For example, additional user interfaces dedicated to governance may be developed. Likewise, while voting currently takes place on-chain through the Governance Contract, some successful votes are administered and implemented by the Obol Association, which should not be the case indefinitely. + +Please see the toolkit on the forum [here](https://community.obol.org/t/governance-toolkit/207). + +## Delegates’ Role in the RAF + +The role of Delegates in the RAF is to allocate votes to projects that have made substantial positive impact on the Obol Collective’s Decentralized Operator Ecosystem. Vote allocation is proportional to the Delegates’ delegated power. To determine the funding amounts, the [quadratic funding](https://qf.gitcoin.co/) mechanism is used, to ensure a balanced and equitable distribution of influence. + +Visit read [the delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) on the forum. + +## Delegate Compensation + +Starting August 2025, active delegates will be eligible for compensation based on their participation and contributions. This is determined using the **Delegate Reputation Score (DRS):** a scoring system that evaluates each delegate’s voting, rationale, and forum activity. Only delegates with a score of **65 or higher** will qualify for rewards. + +For full details on DRS and how compensation works, see the [Delegate Reputation Score & Compensation page.](delegate-guide/delegate-reputation-score-and-compensation.md) diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md b/versioned_docs/version-v1.6/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md new file mode 100644 index 0000000000..7874f36dc3 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md @@ -0,0 +1,101 @@ +--- +sidebar_label: "Delegate Reputation Score & Compensation" +slug: /community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation +--- + +# Delegate Reputation Score & Compensation + +## Delegate Reputation Score & Compensation + +As the Obol Collective moves toward more mature governance, we are introducing a new system to help improve delegate accountability and guide token holder decisions: the **Delegate Reputation Score (DRS)**. + +This mechanism is part of a broader initiative to evolve token governance beyond simple vote counts but toward systems that reward quality participation and reinforce long-term alignment. + +The Obol Collective is among the first DAOs to integrate this model, developed in collaboration with [Tally](https://www.tally.xyz/) and [Curia](https://obol.curiahub.xyz/delegate), helping to pioneer a new standard for **reputation-backed delegate governance**. + +## What is the Delegate Reputation Score (DRS)? {#what-is-the-delegate-reputation-score-drs} +The Delegate Reputation Score is a reputation system. It gives each delegate a score from 0 to 100 based on their behaviour across three core dimensions: + +* **Voting participation** +* **Forum rationale submissions** +* **Forum engagement (discussion and replies)** + +These inputs are tracked over a rolling window of proposals, with scoring updates happening after [every **governance cycle** (every 21 days)](https://app.gitbook.com/s/ym0xLVqLq5ZCK1Q02khi/community-and-governance/governance/token-house#token-house-governance-proposal-process). The current scoring logic can be found in full detail on [Curia’s documentation](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f), which also serves as the canonical source of truth. + +:::tip +**When does my DRS update?** + +Scores are updated every 21-day governance cycle, but with a 6-day delay after the submission window closes. + +This ensures all proposals, including those submitted just before the deadline, have completed their full voting period before scores are recalculated. This buffer guarantees consistency and fairness across the cycle. +::: + +Delegates can view their scores, and token holders can browse and filter delegates based on their reputation and activity levels directly on [Tally](https://www.tally.xyz/gov/obol/delegates). + +### Why it matters {#why-it-matters} +CommentThe DRS is designed to: + +* Help token holders delegate more effectively, with clearer visibility into how delegates are behaving +* Increase accountability by making governance activity measurable and comparable +* Reinforce quality and trust within the delegate set + +In practice, this means token holders are strongly encouraged, through the UI and incentive systems, to **delegate to high-DRS delegates**, while delegates are incentivized to maintain an active and transparent presence in the Collective’s governance. + +_**This is not just a dashboard feature. DRS has real consequences for rewards and visibility.**_ + +### Delegate Statuses by DRS + +Delegates can fall into different categories based on their Delegate Reputation Score (DRS), which is recalculated after every governance cycle. These statuses help token holders understand delegate behavior and make informed delegation decisions: + +* Active: Delegates with a DRS ≥ 65 are considered _active. T_his is the ideal status. Active delegates are eligible for compensation and prominently displayed in the UI to encourage token holders to delegate to them. + * Active (New): A delegate with a DRS ≥ 65 but who has participated in fewer than 5 proposals. While still considered active, this tag highlights that the delegate is relatively new, and their track record is limited. +* Inactive: Delegates with a DRS < 65. These delegates have either skipped votes or failed to post rationales, indicating lower governance engagement. + * Inactive (New): New delegates (fewer than 5 proposals) whose early participation has not met the DRS threshold. This tag signals limited history and insufficient engagement so far. +* Ghost: Delegates who have received voting power but have never participated in any governance vote. Once they vote on a proposal, they’ll transition into an active or inactive status depending on their initial DRS, and will also carry the “new delegate” tag until they surpass 5 evaluated proposals. + +### Bootstrapping New Delegates + +To avoid penalizing new contributors, DRS includes a bootstrapping mechanism. A delegate’s first vote will trigger their scoring process, and their initial DRS will be calculated based on that single proposal. Over time, the DRS evolves into a moving average across the last 5 proposals they were eligible to vote on. This ensures: + +* New delegates who actively participate from the start can achieve a high DRS immediately +* Inconsistent delegates see their score adjust quickly +* A consistent track record is required to maintain an active status + +Additionally, new delegates will be visibly tagged as such in the UI, signaling that their DRS is based on limited history. This helps token holders assess delegation options with full context and encourages early but consistent engagement. + +This design balances the need to reward early participation while preventing score manipulation. Active delegates (even if new) become eligible for compensation as soon as they meet the DRS threshold. + +## Delegate Compensation + +_Delegate Compensation is not live yet. It is scheduled to launch in the second part of August 2025._ + +We are also introducing **delegate compensations**, funded by the Delegate Rewards Pool. Compensation is **gated by DRS**: only delegates with a score of **65 or above** are considered “active” and eligible. + +Once classified as active, rewards are distributed using a **square root model**, based on delegated voting power. This model was selected to strike a balance between influence and fairness: + +* It reduces reward concentration among the largest delegates +* It supports smaller, high-performing delegates +* It helps foster a more pluralistic and sustainable governance ecosystem + +This approach is experimental and will be closely monitored. Over time, we may revisit weighting or distribution methods based on observed outcomes. + +### **Why Delegate Compensation?** + +At Obol, we believe that **no one should work for free. B**ut we also recognize that **not all participation is equally meaningful**. Delegate compensation isn’t about paying people to hold tokens or rubber-stamp votes. It’s about rewarding those who consistently engage with care, post structured rationales, and help the Collective navigate complex governance questions with thoughtfulness and integrity. + +Compensation is now earned through **visible, active contribution —** whether through dissent, alignment, or creative proposals — as long as it’s expressed in a way that moves the Collective forward. Good-faith disagreement and diversity of thought are part of what makes a governance system resilient. That’s the work we want to support. + +## A collaborative standard + +The DRS is a shared initiative between Obol, Tally (UI and standardization), and Curia (calculation and onchain oracle). While the Obol Collective is among the first to adopt this system, the hope is that it will be used by other DAOs seeking to upgrade their delegate models. + +We are proud to help drive this standard forward and will continue sharing learnings as we refine the system in practice. + +## Resources + +* [Tally Delegate Portal](https://www.tally.xyz/gov/obol/delegates) – see live DRS scores, search delegates, and explore participation history +* [Curia Dashboard](https://obol.curiahub.xyz/delegate) – DRS calculation details and complementary metrics +* [Curia's Source of truth for scoring logic](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f) – Broken down calculation of DRS +* [OIP-4: Delegate Compensation & DRS Scoring](https://community.obol.org/t/oip-4-delegate-compensation-and-delegate-reputation-score-integration-for-stobol/522) – original governance proposal + +\\ diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/raf/README.md b/versioned_docs/version-v1.6/community-and-governance/governance/raf/README.md new file mode 100644 index 0000000000..44acaa1f05 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/raf/README.md @@ -0,0 +1,76 @@ +--- +description: "The RAF" +sidebar_label: "The RAF" +slug: /community-and-governance/governance/raf +--- + +# The RAF + +Obol’s Retroactive Funding (RAF) mechanism is designed to strengthen and promote the decentralisation of Ethereum's settlement layer by rewarding projects that add value and drive impact for Ethereum’s decentralisation. Read more about the Obol RAF [here](https://blog.obol.org/1-percent-for-decentralisation/). + +Voting and funding distributions occur over a series of **Obol Retroactive Fund (RAF)** rounds, with OBOL token Delegates determining how funds from the RAF are allocated. The first RAF round will open in February 2025. + +## Overview of the Obol RAF: + +* Any project that meets the RAF round’s criteria can make an application. +* OBOL Token Delegates vote on applications proportional to their delegated power and using [quadratic funding](https://qf.gitcoin.co/). +* The Obol RAF rounds occur at intervals and include phases for scoping, application creation, application review, voting, and funding distribution. +* The Obol Association will collect information from projects to distribute grants, including KYC, where required. + +Below is described the steps within each RAF round. Each step takes approximately one week.\\ + +![](/img/gitbook/image-53.png) + +### Step 1: Scoping + +The scope of the round’s impact and the amount of funding to be allocated is defined by the Obol Association at the outset of the round and posted on the Obol Forum. + +### Step 2: Application Registration + +Projects are invited to create an application on the [RAF App](http://raf.obol.org/). Any project or team can apply, but in the future, governance may decide that an application needs to be made by someone holding a minimum amount of OBOL tokens. + +Once a RAF round is opened, to apply for the Obol RAF, projects can create an application on [raf.obol.org](http://raf.obol.org/) by following these steps: + +1. **Create an Application:** Fill out the application form using the [RAF App](http://raf.obol.org/). +2. **Describe Impact:** Specify the category of the project and its impact. + +### Step 3: Application Review + +A subset of OBOL Delegates appointed by the Obol Association reviews applications to ensure compliance with the application rules. + +The Obol Association will also review applications to filter out spam or applications that do not align with the mission of the Obol Collective. + +### Step 4: Voting + +OBOL Delegates vote on projects in proportion to their voting power. Here’s how it works: + +1. **Eligibility:** Every address that has been delegated voting power by OBOL Token holders can submit votes. +2. **Voting Process:** Delegates vote using the [raf.obol.org](http://raf.obol.org) app. Depending on the type of application being reviewed, a specific set of criteria should be used to judge a project's contributions to the Obol Collective. + +:::warning +The Obol Association will monitor votes to ensure contributors are not voting for projects they are directly involved in or where a substantial conflict of interest may be present. Delegates are expected to act in accordance with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. +::: + +### Step 5: Tallying Results + +The voting power of each OBOL Token Delegate is proportional to the amount of OBOL tokens delegated to them. However, the funding results are calculated using [quadratic funding](https://qf.gitcoin.co/), meaning that the square root of the votes is used to determine the final allocation. This approach ensures a broader distribution of funding across the Obol Collective, rather than allowing a small number of winners to dominate. + +### Step 6: Compliance + +The Obol Association will review the list of selected projects, adjust if necessary and collect information from them to distribute the grant legally compliantly (including completing KYC if required). + +### Step 7: Funding distribution + +The overall reward amount for the round is divided among the winning projects based on the delegates' vote and allocation according to the quadratic funding mechanism. + +### **Step 8: Community retrospective** + +After each round, The Obol Association will conduct a retrospective and gather community feedback. + +## Guides for each Round + +RAF1: see the [RAF1 guide](https://community.obol.org/t/guide-for-raf-round-1-raf1/227) in the forum. + +## RAF1 Summary & Insights + +Head over to [raf1-guide.md](raf1-guide.md "mention") to find the results, top projects, and key takeaways from our first round. diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/raf/raf1-guide.md b/versioned_docs/version-v1.6/community-and-governance/governance/raf/raf1-guide.md new file mode 100644 index 0000000000..0acc913186 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/raf/raf1-guide.md @@ -0,0 +1,27 @@ +--- +sidebar_label: "RAF #1" +slug: /community-and-governance/governance/raf/raf1-guide +--- + +# RAF #1 + +## Learnings from RAF Round 1 + +Our first Retroactive Funding round (RAF1) awarded 1 million OBOL to 46 projects using a quadratic voting mechanism. Projects were evaluated on technical impact, contribution to decentralization, and public goods alignment. + +### Top-funded projects included: + +* Dappnode — integrated Obol into their Dappstore, enabling 16k+ validators to use Obol setups. +* Ethereum on ARM — ran distributed validators on low-cost devices. +* Stereum — offered one-click node deployment with Obol pre-installed, backed by strong GitHub and beaconcha.in adoption metrics. + +### Key learnings: + +* Impact evaluation is challenging without clear data; future rounds may require stronger entry thresholds. +* Quadratic voting worked to elevate broadly supported projects, but needed clearer onboarding. +* Delegates requested better UX for wallets and real-time visibility into vote progress. +* Community engagement was strong but limited in feedback volume — improving outreach will be a focus + +_**We’re using these insights to shape future RAF rounds, with an emphasis on transparency, fairness, and long-term ecosystem impact.**_ + +👉 [Read the full blog post here](https://blog.obol.org/raf1-results/) diff --git a/versioned_docs/version-v1.6/community-and-governance/governance/token-house.md b/versioned_docs/version-v1.6/community-and-governance/governance/token-house.md new file mode 100644 index 0000000000..25a60f8ed3 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/governance/token-house.md @@ -0,0 +1,121 @@ +--- +description: "The Token House" +sidebar_label: "The Token House" +slug: /community-and-governance/governance/token-house +--- + +# The Token House + +In the Token House, OBOL Token holders are responsible for submitting, deliberating, and voting on various Obol Collective governance proposals. + +## Overview of the Obol Token House + +* Proposals are reviewed and voted on in three-week cycles. + +:::info +You can subscribe to the public calendar [here](https://calendar.google.com/calendar/u/0?cid=Y183YzQ0ZmYwZjM5ODE4ZTcyODg2OTM2MmI4ZWEyMGNmMDdhMmZmMmZiMzMxYjE2MjMwYzg3ZjQxZGRiYjA4N2ViQGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20\&ref=blog.obol.org) so you always know where the current cycle stands. +::: + +* In the first week, anyone may draft a proposal of any type based on [this template](https://community.obol.org/t/proposal-template/208) and post it on the [Forum](https://community.obol.org/) with \[Draft] in the title. Delegates, Obol Collective members, and the general public can provide feedback on proposals in the forum, which should be incorporated into the proposal using the author’s best judgment. +* Once your proposal has been approved by four top-100 Delegates (by voting power), add a link to your proposal to the Voting Cycle Roundup forum thread by the last day of Week 2, and update the title from \[Draft] to \[Final]. The proposal then moves on to Week 3: Voting. +* If your proposal is passed, the Obol Association will facilitate its administration, including distributing approved OBOL Tokens grants. +* If your proposal fails, you can make a new proposal in the next cycle, specifying how you have incorporated significant changes from your first proposal.\\ + + ![](/img/gitbook/Token_house.png) + +## Token House Governance Proposal Process + +Anyone can submit a proposal to the Token House by using the Governance Portal. Proposals are accepted or rejected using a voting process. A proposal must be one of the valid proposal types listed below and follow the voting process described here. + +All governance proposals go through a 3-week cycle. Each “week” runs from Thursday at 7:00 pm GMT until Wednesday at 7:00 pm GMT. + +### Valid Proposal Types + +All governance proposals must fall within one of the following categories: + +* Ecosystem grants +* Protocol upgrades +* Token inflation adjustment +* Treasury allocations +* Work agreements +* Veto on the Obol RAF operations + +The different requirements for submission and approval of each Proposal Type are summarized below. If a specific template is not specified below, proposals should follow this standard proposal template. + +All Ecosystem grant applications are processed by the Association. + +Below are listed types of Token House Proposals. Each has a two-week review period plus one week voting window, with an approval threshold of 51%. + +| Proposal Type | Description | Submission Requirements | +| :-----------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------- | +| Ecosystem grants | The Obol Association’s treasury may be used to support development of the Collective and/or growth of the ecosystem via the proposal template. | Forum proposal + On-Chain Voting | +| Token inflation adjustment | Changes to the OBOL Token Contract or its supply. | Forum proposal + On-Chain Voting | +| Treasury Appropriations | The amount of OBOL Tokens the Obol Association may spend or distribute annually | Proposal initiated by the Association + On-Chain Voting | +| Work agreements | Formal arrangements between the Obol Association and contributors, teams, or organizations tasked with advancing specific initiatives or responsibilities within the ecosystem | Forum proposal + On-Chain Voting | +| Veto on the Obol RAF operations | The veto mechanism serves as a safeguard against decisions or actions within the RAF operations that are misaligned with the mission of decentralization, transparency, or the collective interests of the community. | Forum proposal + On-Chain Voting | +| Protocol upgrades | Scheduled changes to the on-chain smart contracts comprising the protocol or governance contracts. | Forum proposal + On-Chain Voting | +| SQUAD Goals | It reflects the aim of establishing shared, strategic, and community-driven objectives. Goals are set annually, with each cycle beginning in April. | Forum proposal + On-Chain Voting | + +### Weeks 1-2: Feedback and Review + +All proposal types should be posted to the [Obol Forum](https://community.obol.org/) for review. Proposal authors are expected to respond to feedback from Obol Collective members and Delegates. + +Proposals should be: + +* Submitted as a new discussion thread on the [Governance Forum](http://community.obol.tech/) in the appropriate Proposal Category. +* Marked with \[Draft] in the title. +* Formatted and contain information consistent with the [standard proposal template](https://community.obol.org/t/proposal-template/208). + +Before the end of Week 2, a governance administrator will create a Voting Cycle Roundup thread in the forum summarising all the proposals that meet the voting requirements for Week 3 Voting. + +For proposals to proceed to Week 3, four of the top 100 delegates by voting power must give explicit approval on the discussion thread. Delegates may signal approval by pasting the following comment on the proposal discussion thread: _”I am an Obol Delegate \[link to your delegate commitment in your Tally profile] with sufficient voting power, and I believe this proposal is ready to move to a vote."_ + +If a Delegate approves a proposal to move to a vote, it does not endorse that proposal. It simply signifies that they believe the proposal is ready to move to a vote. + +After receiving the required approvals, the author should update the proposal title from \[Draft] to \[Final] and add a link to their proposal in the Voting Cycle Roundup thread by the last day of Week 2 at 19:00 GMT. Authors should also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal’s progress. Proposal authors should include relevant links if feedback was gathered outside the Forum (e.g., on Discord). + +If a proposal author does not get explicit approval or wants more time for feedback, they should not include their proposal in the Voting Cycle Roundup thread. Instead, they should continue to seek community feedback and submit an updated proposal in the next voting cycle. + +:::warning +If a proposal that did not receive explicit approval through the steps above is submitted to the voting portal, the Obol Association reserves the right to cancel it onchain. While the Association is currently working to formalize this cancel authority within the Governor contract, this measure helps preserve governance integrity and ensures that only properly vetted proposals are voted on. +::: + +### Week 3: Publish a Proposal Onchain and Voting + +During Week 3, a wallet holding at least [30,000 OBOL in voting power](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c#readContract) must publish the proposal on the [Obol Governance Platform](https://www.tally.xyz/gov/obol).\ +After publication, there is a 24-hour voting delay, during which the proposal can be canceled if necessary. The voting delay is the amount of time between when a proposal is submitted and when it goes up for voting. The delay gives token holders time to delegate their voting power before the vote starts or buy more votes. Governor takes a snapshot of all the voting power at the start of voting. Read more [here](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/how-to-pick-governor-parameters#how-to-pick-the-voting-delay). + +:::warning +Important: Any proposal published on Tally must exactly match the version approved by top delegates on the forum—word for word. Adding new elements that were not explicitly approved is strictly forbidden. Additionally, proposal authors must keep the first post of the forum thread updated to reflect the latest version, so readers don’t have to search the comment section for changes. +::: + +\ +After the 24 hours, Delegates (including OBOL Token holders who have self-delegated) vote on proposals via the [Obol Governance Portal](https://vote.obol.org/). All proposals are included in voting if they were added to the Voting Cycle Roundup thread before the deadline and have the approval of four top-100 delegates. + +A governance proposal is **approved** if it satisfies two requirements: + +* **Quorum:** A minimum number of OBOL Token votes measured as _a % of the total votable OBOL Token supply, as of the start of the voting period._ “Votable supply” is the total amount of OBOL Tokens that have been delegated (including to oneself) and, therefore, can participate in voting. The current definition for the OBOL Token House is 0.84% of minted supply. +* **Approval threshold:** The minimum _% of votes cast in support relative to the total number of votes._ The current definition for the OBOL Token House is 0.01% of minted supply. + +A snapshot is taken at the start of each voting period to determine each delegate’s voting power. Voting is hosted on the Obol Governance Portal. + +If a proposal is submitted for a vote and does not pass, the proposal will not be executed. If a proposal author wishes to iterate on a rejected proposal, they should: + +1. Create a new proposal thread on the Forum. +2. Include a link to the first proposal that did not pass. +3. Clearly identify what has changed in the new proposal. + +:::warning +If the same proposal fails to pass two consecutive times (i.e., it is rejected onchain twice in a row), it may not be reintroduced or submitted again for a minimum period of 5 **governance cycles** — roughly equivalent to 3.5 **months** (based on the current 3-week cycle length). This ensures that only well-formed, broadly supported proposals proceed and discourages repeated cycling of the same topic without meaningful revision or support. +::: + +### Timelock Delay + +After the voting period ends, if the proposal passes, there will be a 5-day timelock delay. The timelock delay is the minimum time required between the approval and execution of a proposal. This delay gives stakeholders a final opportunity to review and react before the proposal is implemented. Read more [here](token-house.md#implementation). + +## Implementation + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails. diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/README.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/README.md new file mode 100644 index 0000000000..4daa098a9c --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/README.md @@ -0,0 +1,105 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/obol-token +--- + +# The OBOL Token + +The OBOL Token is central to the governance and operation of the Obol Collective. It serves multiple purposes that are essential to its functioning. + +**OBOL Token Transferability:** With the approval of[ OIP-2](https://community.obol.org/t/oip-2-unlock-obol-token/317/30), the OBOL Token is set for a strategic and well-planned unlock. The tokens will be unlocked on the 7th May 2025 at 11:00 UTC, following the completion of centralized exchange listings. Please go to [claim.obol.org](https://claim.obol.org) to unlock airdrop tokens. + +## Token Contract + +The official token contract address of the OBOL Token is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7) + +## Official Uniswap Pool + +The official Uniswap Pool for the OBOL Token is [https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434](https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434) + +## Verified Contract Addresses {#verified-contract-addresses} +The following smart contracts power OBOL staking, governance, and reward distribution on Ethereum mainnet. + +
+ +Governor Contract + +* **Address:** [`0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c`](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c) + +- **Purpose:** Manages onchain proposal lifecycle and voting logic for Token House governance. +- **What you can find onchain:** + * Voting thresholds + * Quorum settings, + * Delay/period configs, + * Proposal and vote history. + +
+ +
+ +Obol Staker + +* **Address:** [`0x30641013934ec7625c9e73a4D63aab4201004259`](https://etherscan.io/address/0x30641013934ec7625c9e73a4D63aab4201004259) + +- **Purpose:** This is the base layer of the Obol staking system. It facilitates the basic mechanics of staking, such as managing deposits, forwarding governance delegation, and streaming rewards based on earning power. +- **What you can find onchain:** + * Total OBOL staked in the contract + * Stake, earning power, rewards and balances on a granular, per-deposit basis + * Current reward rate and configuration + * Contract events (e.g. `Staked`, `Withdrawn`) + * Interactions for staking/unstaking + +
+ +
+ +stOBOL (ERC-20 Token Contract) + +* **Address:** [`0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC`](https://etherscan.io/address/0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC) +* **Purpose:** A liquid ERC-20 representation of staked OBOL built on top of the Obol Staker. It adds features like transferability, reward auto compounding, and the ability to use a staked OBOL position in other protocols. Holders retain the ability to delegate their staked tokens to the governance delagate of their choice. +* **What you can find onchain:** + * ERC-20 metadata (name, symbol, decimals) + * Total supply and balances + * Transfer history + * Allowances / approvals + * Voting power interface (via `getVotes` and `delegates`) + * Event logs for delegation changes + +
+ +
+ +Reward Notifier + +* **Address:** [`0x384dd81047F88eE35DE75DA1149943B8e62d8802`](https://etherscan.io/address/0x384dd81047F88eE35DE75DA1149943B8e62d8802) +* **Purpose:** Manages the distribution of tokens to the staking contract so they can be streamed as rewards to stakers. +* **What you can find onchain:** + * Current and past reward rate values + * Administrative role settings (who can push updates) + * Timing/config changes made through proposals + * Events like `RewardRateUpdated` + +
+ +
+ +Auto Delegate (Overwhelming Support Strategy) + +* **Address:** [`0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158`](https://etherscan.io/address/0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158) +* **Purpose:** Implements the “Overwhelming Support” auto-delegation strategy. This contract casts votes on behalf of un-delegated or transferred stOBOL when proposals receive strong community support. This mechanism uses tokens that would otherwise not be available in governance to ensure uncontroversial proposals will meet quorum. +* **What you can find onchain:** + * Parameters like `supportThreshold`, `subQuorumBips`, and `votingWindow` + * Proposals voted on by the strategy + * Vote power amounts cast + * Event logs showing execution activity + * Wallets or protocols interacting with auto-delegation logic + +
+ +## Learn more about... + +[token-utility.md](token-utility.md) +[staking-and-stobol.md](staking-and-stobol.md) +[token-distribution-and-liquidity.md](token-distribution-and-liquidity.md) +[token-holders-faq.md](token-holders-faq.md) +[tge-faq.md](tge-faq.md) diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/staking-and-stobol.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/staking-and-stobol.md new file mode 100644 index 0000000000..f2c58623fa --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/staking-and-stobol.md @@ -0,0 +1,78 @@ +--- +description: "This page explains how OBOL staking works, the role of stOBOL, and what happens when tokens are delegated, transferred, or used in DeFi protocols. You can stake and unstake OBOL via stake.obol.org." +sidebar_label: "Staking & stOBOL" +slug: /community-and-governance/obol-token/staking-and-stobol +--- + +# Staking & stOBOL + +## Overview + +Staking allows OBOL token holders to participate in governance while earning rewards. When you stake OBOL, you receive a liquid staking token called stOBOL. This token is transferable, composable in DeFi, and earns staking rewards while maintaining governance power, as long as it remains in the same address that originally staked the OBOL Tokens. It represents a flexible and powerful tool to both support the network and engage in the broader ecosystem. + +stOBOL unlocks new opportunities for participation. It is yield-bearing, enables seamless governance engagement, and is expected to be increasingly integrated across DeFi platforms. If it is transferred elsewhere, direct delegation is removed and governance power is reassigned an Auto-Delegate, preventing governance attacks. The voting behaviour of the Auto-Delegate is determined by the active strategy. + +### To Recap + +* stOBOL is a liquid staking token received when you stake OBOL. +* It allows users to earn staking rewards which auto-compound while retaining governance power. +* stOBOL is fully transferable (ERC-20) and can be used in DeFi (e.g., as collateral). + +## Key Concepts + +
FeatureOBOLstOBOL
Governance voting✅ (direct or delegated)✅ (only if kept on original staking address, otherwise governance power reallocated to the Auto-Delegate)
Transferable
Used in DeFi✅ (less efficient, not yield-bearing)✅ (yield-bearing)
Earns staking rewards
+ +## Delegation & Governance + +Governance power is fundamentally tied to the OBOL Token. When OBOL is staked, the governance power does not transfer to stOBOL itself but remains associated with the underlying staked OBOL. stOBOL serves as a representation of that staked position, surfacing its governance power **only while being held in the same address** that originally staked the OBOL. + +If stOBOL is transferred to another address or smart contract, governance power is not automatically preserved. Instead: + +* By default, the governance power is reassigned to the **Auto-Delegate**. +* However, the receiving address or smart contract **can explicitly delegate** the voting power of its stOBOL to a delegate of choice, if such functionality is supported. + +This design ensures that governance power follows clear, transparent rules: + +* **No double-counting**: the OBOL held in the staking contract is not counted separately from the stOBOL in circulation. +* **No governance arbitrage**: someone cannot gain voting rights simply by borrowing or acquiring stOBOL without also controlling the original staking delegation. + +If stOBOL is used in DeFi protocols (e.g., as collateral on Morpho), governance power defaults to the Auto-Delegate unless the protocol itself implements explicit delegation support for pooled stOBOL assets. + +## How the Auto-Delegate Strategy Works (Current: Overwhelming Support) + +When a liquid staking token (like stOBOL) is transferred, any previous delegation is removed. To prevent this from harming quorum or enabling governance attacks, the system can route that voting power through the Auto-Delegate strategy. The first strategy implemented is called the "Overwhelming Support". This fallback strategy only casts votes using its accrued governance power **in favor** of a proposal when all the following conditions are met: + +* **Sub-quorum reached:** At least 66% of the quorum is already met by FOR votes (`subQuorumBips = 66%`). +* **High support threshold:** At least 90% of votes cast so far are FOR votes (`supportThreshold = 90%`). +* **Within final voting window:** The proposal is within \~2.5 days of its deadline (`votingWindow = 14400` blocks). + +If all three criteria are met, the strategy casts its voting power FOR the proposal. If not, it abstains. + +This ensures that fallback voting power (from transferred stOBOL) is only used to support proposals that already have overwhelming community backing. It avoids influencing contentious or split decisions, protecting governance neutrality and reducing capture risk. + +This model preserves network governance while allowing for stOBOL to flow through DeFi protocols. + +Other strategies can be proposed via governance. + +## Summary Flow + +1. OBOL is staked and stOBOL is minted to the staker’s address. +2. While stOBOL remains with the same address, governance power is retained and delegated as usual. +3. If stOBOL is transferred, governance power is removed and reassigned via the current Auto-Delegate strategy (Overwhelming Support). Other strategies can be proposed via governance. + +![](/img/gitbook/stOBOL_03-3-1.png) + +## Additional Notes + +* You can stake and unstake OBOL via [stake.obol.org](https://vote.obol.org/stake). +* Voting and delegation are managed at [vote.obol.org](https://vote.obol.org/). + +The Auto-Delegate and underlying strategies are modular and designed to evolve. It represents an initial approach to handling undelegated voting power, but additional strategies can be proposed by the Collective over time. As the Collective matures, we expect to iterate and improve on these mechanisms together. + +As the protocol evolves, new strategies or staking configurations may be introduced through Collective governance. Feedback from the community helps inform these decisions. + +Have questions? Join our [Discord](https://discord.gg/n6ebKsX46w) or visit the [Governance Forum](https://community.obol.org). + +*** + +_This page will evolve as more staking strategies and integrations are launched._ diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/tge-faq.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/tge-faq.md new file mode 100644 index 0000000000..2d2e3766a6 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/tge-faq.md @@ -0,0 +1,170 @@ +--- +sidebar_label: "TGE FAQ" +slug: /community-and-governance/obol-token/tge-faq +--- + +# TGE FAQ + +## Unlock and Listing + +
+ +How do I unlock my OBOL Tokens received in the Airdrop? + +Starting May 7th at 11:00 AM UTC, visit [**claim.obol.org**](https://claim.obol.org), click **“Unlock”**, and follow the steps. + +
+ +
+ +When is the official TGE date and time? + +The OBOL Token will be listed on exchanges for deposit, trading and withdrawals on May 7th, 2025 at 11:00 AM UTC + +
+ +
+ +Where will the OBOL Token be listed for trading? + +* **Binance**, **Bybit**, **Bitget**, **Gate.io**, **MEXC**, and others. + +- Check [CoinGecko](https://coingecko.com) or [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) for the most up-to-date list. + +
+ +
+ +What are the exact listing times on exchanges? + +* **Binance Alpha** – _May 7 at 10:00 AM UTC_ + +- **Binance Futures** – _May 7 at 10:30 AM UTC_ + +* **Bybit, Gate.io, Bitget, MEXC** – _May 7 at 11:00 AM UTC_ + +
+ +
+ +Where can I track the price of the OBOL Token? + +[CoinGecko](https://coingecko.com) and [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) + +
+ +
+ +Where can I buy the OBOL Token onchain? + +* A **Uniswap v3 pool** will be seeded with initial liquidity. + +- The contract address is [here](https://etherscan.io/address/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434). + +* Anyone can start a pool. Check live prices via **CoinGecko**, or **CoinMarketCap**. + +
+ +
+ +Are there any country restrictions for claiming or trading the OBOL Token? + +* Yes. Each venue has its own restrictions. + +- Unlocking OBOL Tokens received through the Airdrop is subject to the same geo restrictions as claiming. + +
+ +## **Token Supply & Distribution** + +
+ +What is the circulating supply at TGE? + +Approximately 19**%**. Full breakdown is on [CoinMarketCap](https://coinmarketcap.com/currencies/obol/). + +
+ +
+ +Why does Etherscan show 374M tokens instead of 500M? + +For legal and tax reasons, not all tokens are minted yet. + +
+ +
+ +How many tokens were allocated to CoinList, and how many unlock at TGE? + +Details available on the [**Coinlist Sale Page**](https://coinlist.co/obol). + +
+ +
+ +When were unclaimed airdrop tokens returned to the treasury? + +As approved by [**OIP-2**](https://community.obol.org/t/oip-2-unlock-obol-token/317), they were [returned](https://etherscan.io/tx/0x738b4c252bb4613b9945e3b6426ec4ee510c6cdb86027fe20d533c4799a3a331) on **May 2, 2025**. + +
+ +## **Unlocks & Vesting** + +
+ +Can CoinList participants claim at TGE? + +Yes, a portion of their tokens will unlock on May 7th at 11AM UTC per the [**Coinlist terms**](https://coinlist.co/obol). + +
+ +
+ +Will RAF1 tokens be available at TGE? + +RAF1 tokens will be distributed **shortly after TGE**. + +
+ +
+ +When will OBOL Token incentives be claimable? + +Starting May 12, 2025 + +
+ +## **Token Utility** + +
+ +What is the utility of the OBOL Token? + +See the top of the page + +
+ +
+ +What is stOBOL? + +A staked version of the OBOL Token that can be used in DeFi or with restaking platforms. + +
+ +
+ +Can the OBOL or stOBOL Tokens be used in DeFi? + +Yes. More info will follow **post-TGE**. + +
+ +
+ +Are there incentives for providing DeFi liquidity with OBOL or stOBOL? + +**Not at TGE**, but proposals for incentives can be submitted via governance. + +
diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/token-distribution-and-liquidity.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/token-distribution-and-liquidity.md new file mode 100644 index 0000000000..649045f286 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/token-distribution-and-liquidity.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Distribution & Liquidity" +slug: /community-and-governance/obol-token/token-distribution-and-liquidity +--- + +# Token Distribution & Liquidity + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](https://docs.obol.org/community-and-governance/governance/raf)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/token-holders-faq.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/token-holders-faq.md new file mode 100644 index 0000000000..7d8565ad63 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/token-holders-faq.md @@ -0,0 +1,135 @@ +--- +description: "This page is designed to answer the most common questions from OBOL token holders, particularly those holding liquid OBOL or stOBOL." +sidebar_label: "Token Holders FAQ" +slug: /community-and-governance/obol-token/token-holders-faq +--- + +# Token Holders FAQ + +## General + +
+ +What is the OBOL token used for? + +OBOL is the governance token of the Obol Collective. It enables holders to participate in on-chain governance by voting directly or delegating their voting power to delegates. + +OBOL is also used in the [RAF](../governance/raf/), where token holders delegate to vote on which contributors should receive retroactive funding for valuable work. + +In addition, OBOL can be staked to receive stOBOL, a liquid token that accrues staking rewards and retains governance power as long as it remains in the staker’s wallet. This staking mechanism supports long-term alignment and decentralized ownership. + +Finally, both OBOL and stOBOL are being integrated into DeFi protocols, such as liquidity pools, lending platforms (e.g. Morpho), and restaking services (e.g. Eigenlayer, Symbiotic), with more utility expected over time as shaped by community governance. + +
+ +
+ +What is stOBOL? + +stOBOL is the liquid staking token received when you stake OBOL. It earns staking rewards and can be used in DeFi. Holding stOBOL in your wallet preserves your governance power. More info in [staking-and-stobol.md](staking-and-stobol.md "mention") + +
+ +
+ +Where can I see OBOL price, supply, and markets? + +You can track OBOL on [CoinMarketCap](https://www.coingecko.com/en/coins/obol-2) or [Coingecko](https://coingecko.com). These pages include market data, supply information, and live price charts. + +
+ +## Delegation & Governance + +
+ +How do I delegate my OBOL tokens? + +You can delegate via [vote.obol.org](https://vote.obol.org/dao/delegates). Connect your wallet, choose a delegate, and confirm the delegation transaction. + +
+ +
+ +What happens if I stake OBOL? + +You receive stOBOL, which maintains your delegation as long as it stays in your wallet. Once transferred (e.g., to a DeFi protocol), you lose the individual delegation. Voting power is then routed via an [auto-delegation strategy](staking-and-stobol.md#how-the-auto-delegate-strategy-works-current-overwhelming-support). + +
+ +
+ +Can I change my delegate? + +Yes, you can re-delegate at any time through the Collective Portal at [vote.obol.org](https://vote.obol.org) + +
+ +
+ +Does holding OBOL give me passive income? + +Not directly. Only staking OBOL (to receive auto-compounding stOBOL) allows you to earn rewards. + +
+ +## Staking & stOBOL + +
+ +How do I stake OBOL? + +Use [stake.obol.org](https://stake.obol.org) to stake. You’ll receive auto-compounding stOBOL in return. + +
+ +
+ +Can I transfer stOBOL? + +Yes, stOBOL is a fully transferable ERC-20 token. However, if you transfer it, your direct delegation is lost, and your governance power enters the auto-delegation pool. + +
+ +
+ +Where can I use stOBOL? + +stOBOL can be used in DeFi protocols (e.g., as collateral, in LPs, etc.). Integrations are ongoing and will be announced via Discord and Twitter. Integrations are also documented [here](staking-and-stobol.md). + +
+ +
+ +Can I unstake OBOL? + +Yes. You can return stOBOL to the staking contract at anytime without lockup to reclaim your OBOL. Unstaking and restaking interfaces are provided at [stake.obol.org](https://stake.obol.org). + +
+ +## Token Value & Utility + +
+ +What gives the OBOL token value? + +OBOL gains utility through governance rights, staking yield, and its use in DeFi. Long term, its value could be tied to the growth of the Obol Network, including fees, protocol usage, and TVL. + +
+ +
+ +Does OBOL accrue fees? + +Currently, OBOL does not accrue protocol revenue. However, the DAO may vote in the future to direct protocol revenue toward token holders or stakers. + +
+ +
+ +How can I stay up to date on OBOL news? + +Join our [Discord](https://discord.obol.org), follow [@ObolNetwork](https://x.com/Obol_Collective), and check our [Forum](https://community.obol.org) for governance and integration updates. + +
+ +_This page is updated regularly. If your question isn’t listed, reach out via Discord or the Governance Forum._ diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/token-utility.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/token-utility.md new file mode 100644 index 0000000000..e4536f6769 --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/token-utility.md @@ -0,0 +1,46 @@ +--- +sidebar_label: "Token Utility" +slug: /community-and-governance/obol-token/token-utility +--- + +# Token Utility + +## **Governance** + +OBOL Token holders delegate their voting power to delegates who participate in the Token House decision-making processes. This includes voting on proposals affecting the Obol Collective’s direction, upgrades, and funding allocations. Read more about the Token House [here](../governance/token-house.md). + +## **Obol Retroactive Funding (RAF)** + +Token holders delegate their voting power to Delegates, who vote on the projects eligible for retroactive funding. Read more about the Obol RAF [here](../governance/raf/). + +## **OBOL Token Staking** + +As per[ OIP-1](https://community.obol.org/t/oip-1-building-and-enabling-staking-for-the-obol-token/312), OBOL token holders will have the opportunity to stake their tokens, contributing to the security and stability of the Collective by preserving governance while earning rewards and being able to engage in DeFi. Staking involves depositing OBOL tokens in a vault (without lockup) that automatically delegates the Tokens if not done already. In return, stakers receive stOBOL, which automatically accrues OBOL Tokens as rewards as it's price vs OBOL increases. + +This staking program will be implemented in phases, allowing the community to gradually engage in and benefit from the system while reinforcing the decentralization of the Obol Collective. For the first six months, the total rewards will be 0.33% of the total supply, providing early participants with attractive rewards. After this period, the staking rewards may be adjusted based on governance proposals and market conditions. This structured rollout ensures a sustainable and rewarding staking experience while reinforcing the decentralization of the Obol Collective. + +To get started, simply visit [https://stake.obol.org](https://stake.obol.org) and follow the staking flow — no technical setup required. The interface will guide you through selecting your wallet, choosing the amount to stake, and submitting the transaction. + +**You will find more info about the OBOL token staking in the dedicated** [staking-and-stobol.md](staking-and-stobol.md "mention") **section.** + +## **DeFi** + +Plans are in place to launch several DeFi avenues for the OBOL Token post-TGE, such as liquidity pools, lending protocols (e.g. Morpho) and restaking (e.g. Eigenlayer, Symbiotic). + +### Pendle Integration for wstOBOL + +_Note: The Pendle integration is not yet live. It is expected to go live in the first half of October 2025. This information is provided in advance for community awareness._ + +wstOBOL is supported on [Pendle Finance](https://app.pendle.finance), enabling users to access advanced yield strategies with their staked OBOL. wstOBOL is the wrapped version of stOBOL. + +For more info on wstOBOL, refer to our [dedicated page](wstobol.md). + +Through Pendle, users can isolate and trade the future yield of wstOBOL by buying or selling its **Principal Tokens (PT)** and **Yield Tokens (YT)**. + +This opens up new opportunities: holders can lock in fixed yield by purchasing PTs, speculate on rising yield by acquiring YTs, or passively earn through **liquidity provision**, which offers exposure to swap fees and additional PENDLE incentives. Importantly, Pendle pools are **permissionless**, and while the Obol Association has provided initial liquidity to bootstrap the market, anyone can contribute.\ +\ +For more details, refer to the [Pendle Academy](https://pendle.gitbook.io/pendle-academy) and [wstOBOL pool on Pendle](https://app.pendle.finance/trade). + +## **More Utility Coming Soon** + +Via Token House governance proposals in the [Governance Forum](https://community.obol.org/), the Obol community can add more functionality and utility to the OBOL Token. diff --git a/versioned_docs/version-v1.6/community-and-governance/obol-token/wstobol.md b/versioned_docs/version-v1.6/community-and-governance/obol-token/wstobol.md new file mode 100644 index 0000000000..841af39cea --- /dev/null +++ b/versioned_docs/version-v1.6/community-and-governance/obol-token/wstobol.md @@ -0,0 +1,59 @@ +--- +description: "Coming Soon..." +sidebar_label: "wstOBOL" +slug: /community-and-governance/obol-token/wstobol +--- + +# wstOBOL + +## What is wstOBOL? + +When you stake OBOL, you receive stOBOL, a non-rebasing, auto-compounding token. + +* Your stOBOL balance stays constant in your wallet. +* The value of each stOBOL relative to OBOL increases over time as staking rewards accrue. + +Unlike “plain” LSTs like stETH, stOBOL is designed to preserve governance: each staked token maintains its delegation, ensuring governance always reflects the real economic stake. + +**wstOBOL (wrapped stOBOL)** is simply a wrapped version of stOBOL. It **carries the same yield and economics**, with rewards accruing via the same exchange-rate mechanism. The difference lies in integration: + +* stOBOL can introduce a minor 1-wei transfer variance due to its governance-preserving accounting. +* wstOBOL eliminates this by providing a perfectly static balance, making it fully compatible with DeFi protocols that require strict 1:1 transfers. + +Think of wstOBOL as the “DeFi-strict” form of stOBOL. It does not change how rewards work, only how the token behaves when integrated into external systems. + +### Why does wstOBOL exist? + +Some DeFi protocols cannot easily integrate stOBOL’s governance logic. wstOBOL simplifies adoption. stOBOL continues to safeguard governance rights, while wstOBOL ensures smooth DeFi use. + +**Not all integrations require wstOBOL.** Some can use stOBOL directly. We will keep this page updated so users know which path to take for each integration. For example, Pendle requires wstOBOL. + +## How does wrapping work? + +* **Wrapping**: you deposit stOBOL and receive the same amount of wstOBOL. +* **Unwrapping**: you return wstOBOL and receive the same amount of stOBOL. + +The number of tokens is 1:1. The economic value grows over time because **stOBOL’s exchange rate to OBOL increases**, and wstOBOL simply represents the same claim on that growing value. + +## User Flows + +You can manage wrapping and unwrapping directly on our [staking platform](https://vote.obol.org/dao/token/wrap). The process is fully integrated and intuitive: just head to the staking portal and you’ll see the following options: + +* **Stake (OBOL → stOBOL)**: Stake OBOL and receive stOBOL, which auto-compounds and preserves delegation. +* **Unstake (stOBOL → OBOL)**: Exit staking and redeem more OBOL back from stOBOL. +* **Wrap (stOBOL → wstOBOL)**: Convert stOBOL into wstOBOL for use in integrations that require strict accounting. +* **Unwrap (wstOBOL → stOBOL)**: Redeem wstOBOL back into stOBOL 1:1. + +## Where can I use wstOBOL? + +* **Pendle Finance** (yield trading, fixed/floating yield markets). +* Future integrations in lending, borrowing, and liquidity protocols. + +## Risks & Considerations + +* Wrapping/unwrapping requires **gas fees**. +* UX involves an extra step for users who hold stOBOL and want to access these DeFi apps. + +## Learn More + +* [Pendle Documentation](https://pendle.gitbook.io/) diff --git a/versioned_docs/version-v1.6/learn/charon/README.md b/versioned_docs/version-v1.6/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.6/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.6/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.6/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..c2531dd1b3 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/charon/charon-cli-reference.md @@ -0,0 +1,828 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.6.1`](https://github.com/ObolNetwork/charon/releases/tag/v1.6.1). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. + --zipped Create a tar archive compressed with gzip of the cluster directory after creation. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost (default "default") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH+ staked for each). (default 1) + --operator-addresses strings Comma-separated list of each operator's Ethereum address. + --operator-enrs strings Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + --publish Creates an invitation to the DKG ceremony on the DV Launchpad. Terms and conditions apply. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 30s) + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 1m0s) + --zipped Create a tar archive compressed with gzip of the target directory after creation. +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --consensus-protocol string Preferred consensus protocol name for the node. Selected automatically when not specified. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + --graffiti strings Comma-separated list or single graffiti string to include in block proposals. List maps to validator's public key in cluster lock. Appends "OB" suffix to graffiti. Maximum 28 bytes per graffiti. + --graffiti-disable-client-append Disables appending "OB" suffix to graffiti. Increases maximum bytes per graffiti to 32. + -h, --help Help for run + --jaeger-address string [DISABLED] Listening address for jaeger tracing. + --jaeger-service string [DISABLED] Service name used for jaeger tracing. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --otlp-address string Listening address for OTLP gRPC tracing backend. + --otlp-headers strings Comma separated list of headers formatted as header=value, to include in OTLP requests. + --otlp-service-name string Service name used for OTLP gRPC tracing. (default "charon") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") + --vc-tls-cert-file string The path to the TLS certificate file used by charon for the validator client API endpoint. + --vc-tls-key-file string The path to the TLS private key file associated with the provided TLS certificate. +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its validator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + delete Delete a signed exit message from the remote API + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Delete exit message + +Delete a previously signed exit message for a given validator from the remote API. The required flag is either `--validator-public-key` of the validator message you wish to delete or `--all` to delete all validators' exit message. + +```markdown +charon exit delete --help +Deletes a partially signed exit message for a given validator from the remote API. + +Usage: + charon exit delete [flags] + +Flags: + --all Exit all currently active validators in the cluster. + -h, --help Help for delete + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default "./") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Generate and add new validators to a cluster + +The `charon alpha add-validators` command allows you to generate new validators and add them to an existing cluster. This process is very similar to the `charon dkg` ceremony, which requires all node operators to participate, because under the hood it runs the same DKG protocol with additional actions and verifications. + +:::warning +It is not yet recommended to use this command for Mainnet clusters. +::: + +```markdown +charon alpha add-validators --help +Generates and appends new validator keys to an existing distributed validator cluster. + +Usage: + charon alpha add-validators [flags] + +Flags: + --data-dir string The source charon folder with existing cluster data (lock, validator_keys, etc.). (default ".charon") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for add-validators + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --num-validators int The number of new validators to generate and add to the existing cluster. (default 1) + --output-dir string The destination folder for the new (combined) cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the command, should be increased if the command times out. (default 1m0s) + --unverified If charon has no access to the existing validator keys, this flag allows the addition to proceed, but skips hashing and signing the new cluster lock data. charon run must be started with --no-verify flag. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Test subcommands provide test suite to evaluate current cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [PingMeasure PingLoad DirectConn Ping Libp2pTCPPortOpen PingRelay PingMeasureRelay SimulateCustom Ping PingMeasure Synced PeerCount PingLoad Simulate1 Simulate10 Simulate100 Version Simulate500 Simulate1000 Ping PingMeasure PingLoad Ping PingMeasure CreateBlock DiskReadIOPS TotalMemory InternetDownloadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadSpeed AvailableMemory InternetLatency InternetUploadSpeed] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [PingLoad Simulate1 Simulate500 Ping Synced PeerCount Simulate10 Simulate100 Simulate1000 SimulateCustom PingMeasure Version] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [DiskWriteIOPS DiskReadSpeed AvailableMemory TotalMemory InternetDownloadSpeed InternetUploadSpeed DiskWriteSpeed DiskReadIOPS InternetLatency] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure CreateBlock] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad DirectConn Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be exeucted. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.6/learn/charon/charon-networking.md b/versioned_docs/version-v1.6/learn/charon/charon-networking.md new file mode 100644 index 0000000000..3bed5e055d --- /dev/null +++ b/versioned_docs/version-v1.6/learn/charon/charon-networking.md @@ -0,0 +1,82 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview[​](https://docs.obol.org/learn/charon/networking#overview) {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](https://docs.obol.org/learn/charon/networking#internal-validator-stack) and the [_external p2p network_](https://docs.obol.org/learn/charon/networking#external-p2p-network). + +### Internal Validator Stack[​](https://docs.obol.org/learn/charon/networking#internal-validator-stack) {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network[​](https://docs.obol.org/learn/charon/networking#external-p2p-network) {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](https://docs.obol.org/learn/charon/charon-cli-reference): + +* `--p2p-tcp-addresses`: Addresses for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security[​](https://docs.obol.org/learn/charon/networking#libp2p-authentication-and-security) {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](https://docs.obol.org/learn/charon/cluster-configuration#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p’s Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery[​](https://docs.obol.org/learn/charon/networking#libp2p-relays-and-peer-discovery) {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives. Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\\ + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters[​](https://docs.obol.org/learn/charon/networking#scalable-relay-clusters) {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URLs. diff --git a/versioned_docs/version-v1.6/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.6/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..35b677f482 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralised backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long-term decentralisation of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability to remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore a trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.6/learn/charon/dkg.md b/versioned_docs/version-v1.6/learn/charon/dkg.md new file mode 100644 index 0000000000..5f7acf9daa --- /dev/null +++ b/versioned_docs/version-v1.6/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENR's nonce and resign with the client's private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participant's old keys out of a distributed validator in favour of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.6/learn/charon/intro.md b/versioned_docs/version-v1.6/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.6/learn/further-reading/README.md b/versioned_docs/version-v1.6/learn/further-reading/README.md new file mode 100644 index 0000000000..6432497dd7 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/further-reading/README.md @@ -0,0 +1,6 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading diff --git a/versioned_docs/version-v1.6/learn/further-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.6/learn/further-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..45e6731817 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/further-reading/ethereum_and_dvt.md @@ -0,0 +1,55 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum_and_dvt +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +\&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.6/learn/further-reading/peer_score.md b/versioned_docs/version-v1.6/learn/further-reading/peer_score.md new file mode 100644 index 0000000000..e79156eb98 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/further-reading/peer_score.md @@ -0,0 +1,48 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer_score +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of a rated network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.6/learn/further-reading/resources.md b/versioned_docs/version-v1.6/learn/further-reading/resources.md new file mode 100644 index 0000000000..dbd5286202 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/further-reading/resources.md @@ -0,0 +1,59 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/further-reading/resources +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.6/learn/further-reading/testnet.md b/versioned_docs/version-v1.6/learn/further-reading/testnet.md new file mode 100644 index 0000000000..9e69963aa5 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/further-reading/testnet.md @@ -0,0 +1,190 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/further-reading/testnet +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.6/learn/intro/README.md b/versioned_docs/version-v1.6/learn/intro/README.md new file mode 100644 index 0000000000..86437ddd26 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/README.md @@ -0,0 +1,9 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "README" +slug: /learn/intro/intro +unlisted: true +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.6/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.6/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..d495a8050d --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/readme/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General[​](https://docs.obol.org/learn/intro/faq#general) {#general} +#### Does Obol have a token?[​](https://docs.obol.org/learn/intro/faq#does-obol-have-a-token) {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/obol-token/) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is 0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7. + +#### Where can I learn more about Distributed Validators?[​](https://docs.obol.org/learn/intro/faq#where-can-i-learn-more-about-distributed-validators) {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from?[​](https://docs.obol.org/learn/intro/faq#where-does-the-name-charon-come-from) {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node?[​](https://docs.obol.org/learn/intro/faq#what-are-the-hardware-requirements-for-running-a-charon-node) {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster?[​](https://docs.obol.org/learn/intro/faq#what-is-the-difference-between-a-node-a-validator-and-a-cluster) {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine?[​](https://docs.obol.org/learn/intro/faq#can-i-migrate-an-existing-charon-node-to-a-new-machine) {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation[​](https://docs.obol.org/learn/intro/faq#distributed-key-generation) {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator?[​](https://docs.obol.org/learn/intro/faq#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator) {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum number of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-threshold). + +### Obol Splits[​](https://docs.obol.org/learn/intro/faq#obol-splits) {#obol-splits} +#### What are Obol Splits?[​](https://docs.obol.org/learn/intro/faq#what-are-obol-splits) {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in the future a number of other LSPs. + +#### Are Obol Splits non-custodial?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-non-custodial) {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split?[​](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split) {#can-i-change-the-percentages-in-a-split} +Generally, Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work?[​](https://docs.obol.org/learn/intro/faq#how-do-obol-splits-work) {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](https://docs.obol.org/learn/intro/obol-splits). + +#### Are Obol Splits open source?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-open-source) {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-audited) {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](https://docs.obol.org/adv/security/smart_contract_audit). + +#### Are the Obol Splits contracts verified on Etherscan?[​](https://docs.obol.org/learn/intro/faq#are-the-obol-splits-contracts-verified-on-etherscan) {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts?[​](https://docs.obol.org/learn/intro/faq#does-my-cold-wallet-have-to-call-the-obol-splits-contracts) {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits?[​](https://docs.obol.org/learn/intro/faq#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits) {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient), its audit [here](https://docs.obol.org/adv/security/smart_contract_audit), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs[​](https://docs.obol.org/learn/intro/faq#debugging-errors-in-logs) {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](https://docs.obol.org/adv/troubleshooting/errors). diff --git a/versioned_docs/version-v1.6/learn/intro/key-concepts.md b/versioned_docs/version-v1.6/learn/intro/key-concepts.md new file mode 100644 index 0000000000..15e8cfcc73 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/key-concepts.md @@ -0,0 +1,117 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/readme/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimising downtime in mission-critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specialises in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof-of-stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys which together operate as a threshold key for participating in proof-of-stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that need to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 3 | 2/3 | Minimum to tolerate one offline node | +| 4 | 3/4 | Minimum to tolerate one **malicious** node | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +:::warning +Running the same Charon node in two places is considered a malicious (or byzantine) act, you should **take extra care not to run duplicate instances of a particular Charon peer if it is running in a three node setup**, which only tolerates one offline node, not a malicious one. Read more [here](../charon/cluster-configuration#cluster-size-and-resilience). +::: + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.6/learn/intro/launchpad.md b/versioned_docs/version-v1.6/learn/intro/launchpad.md new file mode 100644 index 0000000000..38c76daea3 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/launchpad.md @@ -0,0 +1,51 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/readme/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~** Staking Launchpad**](https://launchpad.ethereum.org/), a public good open-source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high-trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI-friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +| ---------------- | -------------------------------------- | +| Mainnet | https://launchpad.obol.org | +| Gnosis Chain | https://gnosischain.launchpad.obol.org | +| Hoodi | https://hoodi.launchpad.obol.org | +| Holesky | https://holesky.launchpad.obol.org | +| Sepolia | https://sepolia.launchpad.obol.org | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +> \[!TIP] If you created a cluster locally, and didn't use the `--publish` command at the time, you can manually publish it by running this command from the folder with the `cluster-lock.json` in it. +> +> `curl -X POST -H "Content-Type: application/json" -d @cluster-lock.json https://api.obol.tech/v1/lock` + +## Use the Explorer + +Clicking "explore" on the top-right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.6/learn/intro/obol-collective.md b/versioned_docs/version-v1.6/learn/intro/obol-collective.md new file mode 100644 index 0000000000..56ca205974 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/readme/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +The Obol Collective is the largest Decentralised Operator Ecosystem. We provide the technology, opportunities, and community to scale decentralised infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also Byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../further-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](https://docs.obol.org/api), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol's [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx), Obol's Distributed Validator Pod. +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.6/learn/intro/obol-incentives.md b/versioned_docs/version-v1.6/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..c673eb4a77 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/obol-incentives.md @@ -0,0 +1,178 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/readme/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible shortly after the OBOL Token is unlocked (as per O[IP#2](https://community.obol.org/t/oip-2-unlock-obol-token/)) and starts trading. + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralisation](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at any time but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.obol.org](https://discord.obol.org). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | diff --git a/versioned_docs/version-v1.6/learn/intro/obol-splits.md b/versioned_docs/version-v1.6/learn/intro/obol-splits.md new file mode 100644 index 0000000000..77b800bd9c --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/obol-splits.md @@ -0,0 +1,120 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/readme/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators and their surrounding ecosystem of decentralised infrastructure. These contracts include: + +* Withdrawal Recipients: Contracts used for a validator's withdrawal address, enabling the differentiation of principal stake from reward ether. +* Reward Splitting contracts: Contracts to split ether (and tokens) across multiple entities. Developed by [Splits.org](https://splits.org/) + +Key Design Principles the Obol Smart Contract suite include are: + +* That they are secure. All [released](https://github.com/ObolNetwork/obol-splits/releases/) Obol Splits products are [audited by high quality security teams](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments). +* They are not upgradeable. +* They are self-sovereign. Any permissioned actions, such as withdrawal, exit, or operator rotation, are controlled by the user, not an unaccountable set of third parties with the ability to upgrade your contract's behaviour. +* They do not require a token to function. +* They are oracle-free. (Unless you intend to leverage a [swapper](https://docs.splits.org/core/swapper)). +* They divide the reward ether from principal ether such that staking providers can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal and reward_. +* That rewards can be withdrawn in an ongoing manner without exiting the validator. (Some conditions apply). + + +## Optimistic Withdrawal Recipient[​](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient) {#withdrawal-recipients} +![](/img/gitbook/image-15-1-1.png) + +Optimistic Withdrawal Recipients (OWRs) **are the predecessor to Obol Validator Managers**. The primary addition with Validator Managers is the role-based control over validator withdrawals, exits and consolidations. + +Optimistic Withdrawal Recipients allow for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use a splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + +## Split Contracts[​](https://docs.obol.org/learn/intro/obol-splits#split-contracts) {#split-contracts} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Validator Managers focus on the former, split contracts focus on the latter. They are best used in tandem. + +![Obol Validator Manager in Tandem with an Execution Layer Fee recipient splitter contract](/img/gitbook/ovm_splits_overview.png) + +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers[​](https://docs.obol.org/learn/intro/obol-splits#split-controllers) {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. We recommend using a [SAFE wallet](https://safe.global) to manage the Split. + +#### (Gnosis) SAFE wallet[​](https://docs.obol.org/learn/intro/obol-splits#gnosis-safe-wallet) {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administer an editable split. The most well-known deployment of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + +## Deployments + +### Obol Lido Split Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#ols-factory-deployment) + +The `ObolLidoSplit` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/lido/ObolLidoSplitFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | --------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | | +| Hoodi | [0xb633CD420aF83E8A5172e299104842b63dd97ab7](https://hoodi.etherscan.io/address/0xb633CD420aF83E8A5172e299104842b63dd97ab7) | +| Holesky | | +| Sepolia | | + +### OWR Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#owr-factory-deployment) + +The `OptimisticWithdrawalRecipient` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Holesky | [0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df](https://holesky.etherscan.io/address/0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | +| Hoodi | [0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7](https://hoodi.etherscan.io/address/0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7) | + +## FAQ + +### What are Obol Splits? + +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido with Obol Lido Splits, and Native Staking with Obol Validator Managers. + +### Are Obol Splits non-custodial? + +Yes. Unless you were to decide to [deploy an editable splitter contract](obol-splits.md#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. Obol Validator Managers have owners and Role-Based Access Control, but these are self-sovereign and up to the deployer to set and manage. There is no third party with access to or control of your validators unless you grant them such access. + +### Can I change the percentages in a split? + +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +### Are Obol Splits open source? + +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +### Are Obol Splits audited? + +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments) and always deploy contracts only from published [releases](https://github.com/ObolNetwork/obol-splits/releases). + +### Are the Obol Splits contracts verified on Etherscan? + +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +### Does my cold wallet have to call the Obol Splits contracts? + +No. Any address can trigger the contracts to distribute the withdrawn/skimmed ether, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +### Are there any edge cases I should be aware of when using Obol Splits? + +The most important thing to be aware of is what address is the owner of the Obol Validator Manager, whether it has assigned any other addresses any roles, and whether or not the Split contract you are using has been set up with editability and by which address. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is to use a high threshold multi-sign like a SAFE as the `owner`/`controller`, or to renounce ownership and control entirely, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](obol-splits.md#withdrawal-recipients), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. diff --git a/versioned_docs/version-v1.6/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.6/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..becb3a6d90 --- /dev/null +++ b/versioned_docs/version-v1.6/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/readme/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and PKI + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.6/run-a-dv/integrations/README.md b/versioned_docs/version-v1.6/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..77e5bf9a25 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# integrations + diff --git a/versioned_docs/version-v1.6/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.6/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..b7b9b507a4 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,58 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) and other applications. + +### Pre-requisites[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#pre-requisites) {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](https://docs.obol.org/next/adv/advanced/quickstart-sdk) is required. + +### Create a SAFE to own the EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-safe-to-own-the-eigenpod) {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-an-eigenpod) {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-splitter-for-the-block-reward) {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-the-dv-cluster-invite) {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](https://docs.obol.org/next/run/start/quickstart_group) on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](https://docs.obol.org/next/run/integrations/quickstart-sdk) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#deposit-and-restake-your-distributed-validator) {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. + diff --git a/versioned_docs/version-v1.6/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.6/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..ff1a100819 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/integrations/dappnode.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# DappNode + +For setup, see quickstart guide:[​](https://docs.obol.org/next/run/integrations/Dappnode#for-setup-see-quickstart-guide) + +For set-up of a DV using DappNode, see the quickstart guide [Create a DV Alone](https://docs.obol.org/next/run/start/quickstart_alone), and select the appropriate tab for "DappNode". + +### Frequently asked questions[​](https://docs.obol.org/next/run/integrations/Dappnode#frequently-asked-questions) {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster?[​](https://docs.obol.org/next/run/integrations/Dappnode#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-the-validator-and-charon-volumes-to-use-the-same-enr-for-another-cluster) {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC?[​](https://docs.obol.org/next/run/integrations/Dappnode#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag-for-lodestar-vc) {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically.\\ + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol?[​](https://docs.obol.org/next/run/integrations/Dappnode#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-same-dappnode-machine-push-monitoring-data-from-both-clusters-to-obol) {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.6/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.6/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..c987d10c11 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,225 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://operatorportal.lido.fi/modules/community-staking-module) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from Holesky just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using the CSM widget and expanding `Specify Custom Addresses` to set the `Manager Address` to the cluster multi-sig (SAFE) and the `Rewards Address` to the Splits.org splitting contract. Finally, we'll be selecting `Extended` permissions type which grants `Manager Address` ultimate control over the Node Operator. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (this can be the same address used in the SAFE contract). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (recommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol protocol development, thereby earning [Obol Incentives](https://obol.org/incentives) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [protocoldevelopmentfee.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol protocol development. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated the CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create validator keys with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create. +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using your favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM V2 enables a new Operator Type called Identified Community Staker ("ICS"). The squad member who is an ICS should be the one to create the node through the CSM widget. Doing so will ensure the clusters validators receive [ICS benefits](https://blog.lido.fi/unlock-exclusive-benefits-as-an-identified-community-staker/). + +The ICS member will head to [csm.lido.fi](https://csm.lido.fi/) and connect their wallet. + +![](/img/gitbook/image-47.png) + +The ICS member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The ICS member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The ICS member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button. + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.6/run-a-dv/prepare/README.md b/versioned_docs/version-v1.6/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..6d77f77e82 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# prepare + diff --git a/versioned_docs/version-v1.6/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.6/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..da8f61b1da --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,99 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10mb/s internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25mb/s internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimise both performance and cost-effectiveness, it is recommended to prioritise physical over virtualised setups. Such configurations typically offer greater performance and minimise overhead associated with virtualisation, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimise Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimize potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes would potentially impact the fault tolerance of the cluster and as a result should be avoided. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. Be sure to use encrypted communication between your VC and the Charon client, potentially through a cloud-provided network, a self-managed network tunnel, a VPN, a Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), or other manner. + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration/#cluster-size-and-resilience)). + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](./test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +The clusters should consist of a combination of your preferred consensus, execution, and validator clients. It is recommended to include a combination of multiple clients in order to have a healthy client diversity within the cluster, ideally, if any single client type fails, it should be less than the fault tolerance of the cluster, and the validators should stay online/not do anything slashable. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Metrics Monitoring + +As requested by Obol Labs, node operators can push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. Our recommendation for operators is to independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (usually < 24 hours). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.6/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.6/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..1c94049a40 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatibility information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.6/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.6/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..4646c7ed62 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,554 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + + +:::tip + +Adding the `--publish` flag to the below commands, and running the command from the directory containing your `.charon` folder, will submit the test results to the [Obol API](../../api/what-is-this-api.md). Publishing your performance reports grows the staking node dataset, and allows Obol and Ethereum development teams to make data-driven choices regarding the required specs for validating Ethereum. We hope you will consider opting in. + +::: + + + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + + +:::info + +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the `beacon` node and `validator` client tests, you need to point them toward the correct Docker container, this includes specifying the Docker container’s network. Check your docker networks with the command `docker network ls`. When you run the test command, specify the Docker network with `--network `. + +Read more about docker networking [here](https://docs.docker.com/engine/network/). + +::: + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.6.1 alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.6.1 alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + + + + +#### Pre-requisites + +The executable storage tests require `fio` to be installed on your host machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +#### Example run + +```sh +charon alpha test infra +``` + + + + + +#### Example run + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.6.1 alpha test infra \ + --disk-io-test-file-dir=/opt/charon/test +``` + + + diff --git a/versioned_docs/version-v1.6/run-a-dv/running/README.md b/versioned_docs/version-v1.6/run-a-dv/running/README.md new file mode 100644 index 0000000000..515e6cbede --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# running + diff --git a/versioned_docs/version-v1.6/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.6/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..3c7cddf6d9 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +Use any of the following tools to deposit. Please use the third-party tools at your own risk and always double check the staking contract address. + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. diff --git a/versioned_docs/version-v1.6/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.6/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..8bf951f495 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/running/claim-rewards.md @@ -0,0 +1,65 @@ +--- +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +Introduction[​](https://docs.obol.org/next/run/running/claim-rewards#introduction) + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator’s withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +The method for claiming rewards depends on the Cluster's withdrawal configuration, whether it's an [**OWR**](https://docs.obol.org/next/learn/intro/obol-splits#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](https://docs.obol.org/next/learn/intro/obol-splits#exitable-withdrawal-recipient) . The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +\\ + +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](https://docs.obol.org/run/integrations/lido-csm). | + +### Claim Flow[​](https://docs.obol.org/next/run/running/claim-rewards#claim-flow) {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](https://docs.obol.org/next/learn/intro/obol-splits). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +1. All validator rewards are accumulated in the validator's withdrawal address, which is a split wallet. +2. Claims can be triggered in two ways: + 1. **From addresses in the Splitter**: Splitter addresses will see a `Claim All` button. When the first address (e.g., address A) executes `Claim All`, it triggers a multi-call transaction to distribute rewards from all the split wallets associated with a cluster into the Split Main. The Split Main then sends address A’s proportion of the rewards (based on the split configuration at the time of cluster creation). All of this is executed with a single click for the first address. + 2. **From addresses not in the Splitter**: Non-splitter addresses will see a `Distribute All` button instead of `Claim All`. These addresses cannot claim rewards directly but can distribute rewards to the Split Main (subsidizing transaction fees for others). Operators can then claim rewards later by visiting the same cluster details page. +3. Internally, after clicking `Claim All` or `Distribute All`, the split wallet sends the funds to the Split Main contract. +4. The Split Main then sends proportional rewards to **address A**, completing steps 2a, 3, and 4 with a single click. +5. Other addresses (e.g., B, C, D) can later click on `Claim All` to receive their share of the rewards. + +### Launchpad Edge Cases[​](https://docs.obol.org/next/run/running/claim-rewards#launchpad-edge-cases) {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: The `Claimable` column doesn’t match the amount next to the `Claim All` button. {#case-1-the-claimable-column-doesnt-match-the-amount-next-to-the-claim-all-button} +![](/img/gitbook/image-87.png) + +![](/img/gitbook/image-1-1-1-1-1.png) + +In this scenario, someone else (a splitter or non-splitter address) has already distributed rewards to the Split Main (e.g., 0.12 ETH). However, your validators (4 in this case) have earned an additional 0.2 ETH in rewards. Your total effective claimable balance is 0.032 ETH, which you can claim using the `Claim All` button. + +:::info +Your total effective claimable amount will always be displayed next to the `Claim All` button. +::: + +#### Case 2: You don’t see a `Claim All` button but instead see `Distribute All`.[​](https://docs.obol.org/next/run/running/claim-rewards#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all) {#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all} +![](/img/gitbook/image-88.png) + +This happens because the connected address is not listed in the split configuration. You may have used a different operator address from the one in the splitter configuration. You can: + +* Distribute all rewards using the connected address for all operators and claim using your address in the splitter configuration. +* Switch to the splitter address and claim directly. + +Note: It costs the same gas to distribute rewards for one address as it does for all addresses. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows a `Claim All` amount. {#case-3-you-just-created-a-new-cluster-with-no-active-validators-or-rewards-but-it-shows-a-claim-all} +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all `Claim All` buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.6/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.6/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..5401b89f8f --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,933 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction[​](https://docs.obol.org/next/run/running/quickstart-exit#introduction) {#introduction} +Users looking to exit staking entirely and withdraw their full balance back must sign and broadcast a "voluntary exit" message with validator keys which will start the process of exiting from staking. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proportion of principal and rewards. + +There are two ways to sign the partial exit and broadcast the full exit. Both the solutions don't require gas. + +1. **Using the Charon’s exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via launchpad and ability to download partial exits and broadcast them later as required. Users don’t have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use launchpad to monitor exit status and will have to use grafana to query the partial exit status. + +:::info +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +As per your preferences, choose the correct combination of - + +1. **Network** : Mainnet or Holesky +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quanity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +#### Step 1: Submit partial exit {#introduction} + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message.\\ + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](https://docs.obol.org/img/PartialExitsStatus.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch[​](https://docs.obol.org/next/run/running/quickstart-exit#exit-epoch-and-withdrawable-epoch) {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.6/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.6/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..84e9d5c53c --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/running/monitoring.md @@ -0,0 +1,89 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/d6qujIJVk/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show following page. Choose Discord in the `Integration` drop down.\\ + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md). + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.6/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.6/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..36495800df --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,124 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + diff --git a/versioned_docs/version-v1.6/run-a-dv/start/README.md b/versioned_docs/version-v1.6/run-a-dv/start/README.md new file mode 100644 index 0000000000..f8e137e70b --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# start + diff --git a/versioned_docs/version-v1.6/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.6/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..11b5ab1c11 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,201 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](https://docs.obol.org/run/start/quickstart_group) instead for this latter case. +::: + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_alone#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.6.1 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 create cluster \ + --nodes=6 \ + --network=holesky \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead \ + --publish +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](https://docs.obol.org/next/run/start/quickstart_alone#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately.\ +\ +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Holesky testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Set up the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample.holesky .env +``` +::: + + diff --git a/versioned_docs/version-v1.6/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.6/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..8231833848 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,604 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_group#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](https://docs.obol.org/next/run/prepare/deployment-best-practices#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](https://docs.obol.org/next/adv/troubleshooting/errors#docker-permission-denied-error) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client**[**​**](https://docs.obol.org/next/run/start/quickstart_group#prepare-an-execution-and-consensus-client) + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package**[**​**](https://docs.obol.org/next/run/start/quickstart_group#install-the-obol-dappnode-package) + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge**[**​**](http://localhost:3000/run/start/quickstart_group#installing-sedge) + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful**[**​**](http://localhost:3000/run/start/quickstart_group#check-the-install-was-successful) + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +**Collect addresses, configure the cluster, share the invitation** + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + 1. Select the desired amount of validators (32 ETH each) the cluster will run. (Note that the mainnet launchpad is restricted to one validator for now.) + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr) in the "What is your charon client's ENR?" field. + 3. Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. + 4. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions of participating as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +**Join the cluster prepared by the creator** + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address provided to the leader.\\ + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue.\\ + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr).\\ + + ![](/img/gitbook/image-83.png) +6. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +7. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](https://docs.obol.org/next/learn/charon/dkg) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) \\ + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. \\ + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.6.1 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run.\\ + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page.\\ + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +**Create a DV Node Backup** + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present.\\ + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long-term. + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose, further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Holesky testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +```sh +# To prepare the node for the Holesky test network +# Copy ".env.sample.holesky", renaming it ".env" +cp .env.sample.holesky .env + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env +``` + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```sh + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +``` + +:::danger +Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. +::: + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/d6qujIJVk/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). + + + + +:::danger +Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. +::: + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Stop your docker compose + +```sh +docker compose down +``` + +2. Uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +3. Uncomment `EL=el-none` and `CL=cl-none` variables in the `.env` file and comment `EL=el-nethermind` and `CL=cl-lighthouse` variables: + +```sh +... +#EL=el-nethermind +... +EL=el-none +... +#CL=cl-lighthouse +... +CL=cl-none +... +``` + +4. Start your docker compose + +```sh +docker compose up -d +``` + + + + +To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-generate) + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Holesky network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=holesky --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-import-key) + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ holesky teku +``` + +**Sedge Run**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-run) + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. + + + +Use an Ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. + + + +Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. + + + +Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. + + + +:::tip +In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is `:3610`. Read more about Charon's networking [here](https://docs.obol.org/next/learn/charon/networking). +::: + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](https://docs.obol.org/next/run/running/activate-dv) to begin staking. diff --git a/versioned_docs/version-v1.6/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.6/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..8aa5fff0de --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,56 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics to Obol Monitoring" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics to Obol Monitoring + +:::info +This is **optional** and does not confer any special privileges within the Obol Network. +::: + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](http://localhost:3000/run/start/quickstart_overview), and have been provided with **Monitoring Credentials** used to push distributed validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve your Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +#### Update the monitoring token in the `.env` file + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +#### Save the `.env` file and restart Prometheus + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab.\\ + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it.\\ + + ![](/img/gitbook/image-86.png) + + diff --git a/versioned_docs/version-v1.6/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.6/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..371dc03d45 --- /dev/null +++ b/versioned_docs/version-v1.6/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to utilise Distributed Validators for solo or multi-operator staking. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](./create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](./create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.6/sdk/classes/Client.md b/versioned_docs/version-v1.6/sdk/classes/Client.md new file mode 100644 index 0000000000..a19a70f5e8 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/classes/Client.md @@ -0,0 +1,244 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +### Extends + +* `Base` + +### Constructors + +#### new Client() + +> **new Client**(`config`, `signer`?): [`Client`](Client.md) + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | -------- | --------------------- | +| `config` | `object` | Client configurations | +| `config.baseUrl`? | `string` | obol-api url | +| `config.chainId`? | `number` | Blockchain network ID | +| `signer`? | `Signer` | ethersJS Signer | + +**Returns** + +[`Client`](Client.md) + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client: [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +**Overrides** + +`Base.constructor` + +**Defined in** + +index.ts:66 + +### Methods + +#### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`<`string`> + +Accepts Obol terms and conditions to be able to create or update data. + +**Returns** + +`Promise`<`string`> + +terms and conditions acceptance success message. + +**Throws** + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions: [acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +**Defined in** + +index.ts:79 + +*** + +#### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys OWR and Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| --------------------- | ------------------------------------------------------------- | --------------------------------------- | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit: [createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:133 + +*** + +#### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| ------------------- | ----------------------------------------------------------- | -------------------------------------------------- | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit: [createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:254 + +*** + +#### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`<`string`> + +Creates a cluster definition which contains cluster configuration. + +**Parameters** + +| Parameter | Type | Description | +| ------------ | ----------------------------------------------------- | ----------------------- | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +**Returns** + +`Promise`<`string`> + +config\_hash. + +**Throws** + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition: [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +**Defined in** + +index.ts:350 + +*** + +#### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Approves joining a cluster with specific configuration. + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition. + +**Throws** + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition: [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +**Defined in** + +index.ts:415 + +*** + +#### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | ---------------------------------------------------------- | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition for config hash + +**Throws** + +On not found config hash. + +An example of how to use getClusterDefinition: [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +**Defined in** + +index.ts:469 + +*** + +#### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | -------------------------------------------- | +| `configHash` | `string` | The configuration hash in cluster-definition | + +**Returns** + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +**Throws** + +On not found cluster definition or lock. + +An example of how to use getClusterLock: [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +**Defined in** + +index.ts:488 diff --git a/versioned_docs/version-v1.6/sdk/classes/README.md b/versioned_docs/version-v1.6/sdk/classes/README.md new file mode 100644 index 0000000000..d71a58615e --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# classes + diff --git a/versioned_docs/version-v1.6/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.6/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..7e4d9cb8ef --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,16 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------------------ | -------- | ------------- | ----------- | +| `0x00000000` | `1` | Mainnet | types.ts:6 | +| `0x00001020` | `5` | Goerli/Prater | types.ts:9 | +| `0x00000064` | `100` | Gnosis Chain | types.ts:12 | +| `0x01017000` | `17000` | Holesky | types.ts:15 | +| `0x10000910` | `560048` | Hoodi | types.ts:18 | diff --git a/versioned_docs/version-v1.6/sdk/enumerations/README.md b/versioned_docs/version-v1.6/sdk/enumerations/README.md new file mode 100644 index 0000000000..5069f1f6ed --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# enumerations + diff --git a/versioned_docs/version-v1.6/sdk/functions/README.md b/versioned_docs/version-v1.6/sdk/functions/README.md new file mode 100644 index 0000000000..62be7a3a85 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# functions + diff --git a/versioned_docs/version-v1.6/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.6/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..cb920b4b8b --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/functions/validateClusterLock.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock + +> **validateClusterLock**(`lock`): `Promise`<`boolean`> + +Verifies Cluster Lock's validity. + +### Parameters + +| Parameter | Type | Description | +| --------- | ----------------------------------------------- | ------------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | + +### Returns + +`Promise`<`boolean`> + +boolean result to indicate if lock is valid + +### Throws + +on missing keys or values. + +An example of how to use validateClusterLock: [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) + +### Defined in + +services.ts:13 diff --git a/versioned_docs/version-v1.6/sdk/index.md b/versioned_docs/version-v1.6/sdk/index.md new file mode 100644 index 0000000000..d22906b706 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/index.md @@ -0,0 +1,93 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + +# Intro + +**SDK Version:** v2.1.0 + +![Obol Logo](https://obol.org/obolnetwork.png) + +## Obol SDK + +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](https://docs.obol.org/api). + +### Getting Started + +Checkout our [docs](https://docs.obol.org/advanced/quickstart-sdk), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +### Terms and Conditions + +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +### ⚠️ Important Security Notice: + +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +* The private key is securely stored (e.g., in an `.env` file). +* Never commit or push your `.env` file containing the private key to version control. + +### Contributing + +Please review the following guidelines: + +* [How to Report Bugs](index.md#how-to-report-bugs) +* [How to Propose Changes](index.md#how-to-propose-changes) +* [Code Review Process](index.md#code-review-process) + +#### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +#### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +#### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +### Enumerations + +* [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +### Classes + +* [Client](classes/Client.md) + +### Interfaces + +* [ClusterDefinition](interfaces/ClusterDefinition.md) +* [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) + +### Type Aliases + +* [ClusterOperator](type-aliases/ClusterOperator.md) +* [OperatorPayload](type-aliases/OperatorPayload.md) +* [ClusterCreator](type-aliases/ClusterCreator.md) +* [ClusterValidator](type-aliases/ClusterValidator.md) +* [ClusterPayload](type-aliases/ClusterPayload.md) +* [SplitRecipient](type-aliases/SplitRecipient.md) +* [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +* [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +* [BuilderRegistration](type-aliases/BuilderRegistration.md) +* [DepositData](type-aliases/DepositData.md) +* [DistributedValidator](type-aliases/DistributedValidator.md) +* [ClusterLock](type-aliases/ClusterLock.md) +* [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) + +### Functions + +* [validateClusterLock](functions/validateClusterLock.md) diff --git a/versioned_docs/version-v1.6/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.6/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..b57096a0bf --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +Cluster definition data needed for dkg + +## Extends + +- [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | `ClusterPayload.name` | types.ts:73 | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)[] | The cluster nodes operators addresses. | `ClusterPayload.operators` | types.ts:76 | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)[] | The cluster validators information. | `ClusterPayload.validators` | types.ts:79 | +| `deposit_amounts?` | `null` \| `string`[] | The cluster partial deposits in gwei or 32000000000. | `ClusterPayload.deposit_amounts` | types.ts:82 | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | types.ts:90 | +| `version` | `string` | The cluster configuration version. | - | types.ts:93 | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | types.ts:96 | +| `fork_version` | `string` | The cluster fork version. | - | types.ts:99 | +| `uuid` | `string` | The cluster uuid. | - | types.ts:102 | +| `timestamp` | `string` | The cluster creation timestamp. | - | types.ts:105 | +| `config_hash` | `string` | The cluster configuration hash. | - | types.ts:108 | +| `threshold` | `number` | The distributed validator threshold. | - | types.ts:111 | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | types.ts:114 | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | types.ts:117 | diff --git a/versioned_docs/version-v1.6/sdk/interfaces/README.md b/versioned_docs/version-v1.6/sdk/interfaces/README.md new file mode 100644 index 0000000000..b635dbc6dc --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# interfaces + diff --git a/versioned_docs/version-v1.6/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.6/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..4ee32df936 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,24 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +# RewardsSplitPayload + +OWR and Split Proxy Params + +### Extends + +* [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +### Properties + +| Property | Type | Description | Inherited from | Defined in | +| -------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ------------ | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)\[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | types.ts:136 | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for Obol protocol development fee, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | types.ts:139 | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | types.ts:142 | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | types.ts:145 | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | types.ts:153 | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | types.ts:156 | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | types.ts:159 | diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.6/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..281cd48a13 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +> **BuilderRegistration**: `object` + +Pre-generated Signed Validator Builder Registration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | types.ts:184 | +| `signature` | `string` | BLS signature of the builder registration message. | types.ts:187 | + +## Defined in + +types.ts:182 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.6/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..f7467b4436 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +> **BuilderRegistrationMessage**: `object` + +Unsigned DV Builder Registration Message + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient` | `string` | The DV fee recipient. | types.ts:167 | +| `gas_limit` | `number` | Default is 30000000. | types.ts:170 | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | types.ts:173 | +| `pubkey` | `string` | The public key of the DV. | types.ts:176 | + +## Defined in + +types.ts:165 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..643f98978e --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +> **ClusterCreator**: `object` + +Cluster creator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The creator address. | types.ts:52 | +| `config_signature`? | `string` | The cluster configuration signature. | types.ts:54 | + +## Defined in + +types.ts:50 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..e386f0060e --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +> **ClusterLock**: `object` + +Cluster Details after DKG is complete + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | types.ts:235 | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)[] | The cluster distributed validators. | types.ts:238 | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | types.ts:241 | +| `lock_hash` | `string` | The hash of the cluster lock. | types.ts:244 | +| `node_signatures`? | `string`[] | Node Signature for the lock hash by the node secp256k1 key. | types.ts:247 | + +## Defined in + +types.ts:233 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..c12e7caa48 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +> **ClusterOperator**: `object` + +Node operator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The operator address. | types.ts:23 | +| `enr`? | `string` | The operator ethereum node record. | types.ts:26 | +| `fork_version`? | `string` | The cluster fork_version. | types.ts:29 | +| `version`? | `string` | The cluster version. | types.ts:32 | +| `enr_signature`? | `string` | The operator enr signature. | types.ts:35 | +| `config_signature`? | `string` | The operator configuration signature. | types.ts:38 | + +## Defined in + +types.ts:21 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..ab4d99aff2 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +> **ClusterPayload**: `object` + +Cluster configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | types.ts:73 | +| `operators` | [`ClusterOperator`](ClusterOperator.md)[] | The cluster nodes operators addresses. | types.ts:76 | +| `validators` | [`ClusterValidator`](ClusterValidator.md)[] | The cluster validators information. | types.ts:79 | +| `deposit_amounts`? | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | types.ts:82 | + +## Defined in + +types.ts:71 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..266d48a113 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +> **ClusterValidator**: `object` + +Validator withdrawal configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | types.ts:62 | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | types.ts:65 | + +## Defined in + +types.ts:60 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.6/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..592d2f643b --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +> **DepositData**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | The public key of the distributed validator. | types.ts:195 | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | types.ts:198 | +| `amount` | `string` | 32 ethers. | types.ts:201 | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | types.ts:204 | +| `signature` | `string` | BLS signature of the deposit message. | types.ts:207 | + +## Defined in + +types.ts:193 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.6/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..5ec5dcc09d --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +> **DistributedValidator**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | types.ts:215 | +| `public_shares` | `string`[] | The public key of the node distributed validator share. | types.ts:218 | +| `deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\> | The deposit data for activating the DV. | types.ts:221 | +| `partial_deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\>[] | The deposit data with partial amounts or full amount for activating the DV. | types.ts:224 | +| `builder_registration`? | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | types.ts:227 | + +## Defined in + +types.ts:213 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.6/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..c08cb82c83 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +> **ETH\_ADDRESS**: `string` + +String expected to be Ethereum Address + +## Defined in + +types.ts:253 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.6/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..ee7810452c --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +> **OperatorPayload**: `Partial`\<[`ClusterOperator`](ClusterOperator.md)\> & `Required`\<`Pick`\<[`ClusterOperator`](ClusterOperator.md), `"enr"` \| `"version"`\>\> + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. + +## Defined in + +types.ts:44 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/README.md b/versioned_docs/version-v1.6/sdk/type-aliases/README.md new file mode 100644 index 0000000000..9e1ac60271 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# type-aliases + diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.6/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..e40db01a6c --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +> **SplitRecipient**: `object` + +Split Recipient Keys + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `account` | `string` | The split recipient address. | types.ts:125 | +| `percentAllocation` | `number` | The recipient split. | types.ts:128 | + +## Defined in + +types.ts:123 diff --git a/versioned_docs/version-v1.6/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.6/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..3e24994833 --- /dev/null +++ b/versioned_docs/version-v1.6/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +# TotalSplitPayload + +> **TotalSplitPayload**: `object` + +Split Proxy Params + +### Type declaration + +| Name | Type | Description | Defined in | +| -------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)\[] | The split recipients addresses and splits. | types.ts:136 | +| `ObolRAFSplit`? | `number` | Split percentageNumber allocated for Obol protocol development fee, minimum is 1%. | types.ts:139 | +| `distributorFee`? | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | types.ts:142 | +| `controllerAddress`? | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | types.ts:145 | + +### Defined in + +types.ts:134 diff --git a/versioned_docs/version-v1.6/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.6/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..5368c6e179 --- /dev/null +++ b/versioned_docs/version-v1.6/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# walkthroughs + diff --git a/versioned_docs/version-v1.6/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.6/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.6/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_docs/version-v1.7/README.md b/versioned_docs/version-v1.7/README.md new file mode 100644 index 0000000000..1cf9800b4e --- /dev/null +++ b/versioned_docs/version-v1.7/README.md @@ -0,0 +1,8 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "Introduction" +slug: /learn/readme +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..27650c3586 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# advanced + diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/add-validators.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/add-validators.md new file mode 100644 index 0000000000..ff55743164 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/add-validators.md @@ -0,0 +1,69 @@ +--- +description: "Add validators to your existing distributed validator cluster using the charon alpha add-validators command." +sidebar_label: "Adding Validators" +slug: /advanced-and-troubleshooting/advanced/add-validators +--- + +# Adding Validators + +:::warning +This is an experimental feature available starting with Charon v1.6 and should not be used in production (Mainnet) yet. +::: + +You can add validators to your cluster using the `charon alpha add-validators` command. The example below is designed for the default configuration provided by this repository and assumes that the stack uses the Lodestar validator client. + +## Prerequisites + +1. Review the `add-validators` command [CLI reference](https://docs.obol.org/docs/learn/charon/charon-cli-reference). +2. Ensure this folder contains a valid `.charon` directory currently used by the running node. Keep the DV node running during the process. + +## Adding Validators Process + +The examples below are for adding 10 validators. You can use them with any number of validators you would like to add. Run the following command to collectively generate and add 10 new validators with other node operators (similar to DKG): + +```bash +# If you prefer running a pre-built charon binary +charon alpha add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:latest alpha add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --data-dir=/opt/charon/.charon --output-dir=/opt/charon/output +``` + +This command will create a new cluster configuration that includes both existing and new validators. It will also generate the necessary keys for the new validators and deposit data files. The new configuration will be saved in the `output` directory. + +## Making the DV Stack Use the New Validators + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +1. To start using the new configuration (with the added validators), stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` and recognise all validators in the cluster. + +:::info +Steps 1–3 must be performed independently by all node operators, likely at different times. During this process, some nodes will use the old configuration and others the new one. Once the number of upgraded nodes reaches the BFT threshold, the newly added validators will begin participating in the cluster. +::: + +## Current Limitations + +- The new cluster configuration will not be reflected on the Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +- The `add-validators` command supports the KeyManager API (similar to the `dkg` command), but since it may not have direct access to the original private keys if they're not still in the `.charon` folder you are adding validators to, it cannot produce valid cluster lock signatures. In this case, you must use the `--unverified` flag, which means Charon does not hash and sign the new cluster lock file with all the private keys to prove their existence. This requires adding the `--no-verify` flag or `CHARON_NO_VERIFY=true` environment variable to the `charon run` command/container. +- If you use different validator clients, review the keys import script. The old keys in `.charon/validator_keys` remain unchanged, so verify that importing the same keys will not disrupt the validator client's state. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..91890c82c5 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 version-controlled 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 `tempo`. 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 +``` diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/beacon-node-authentication.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/beacon-node-authentication.md new file mode 100644 index 0000000000..ec63bbee2f --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/beacon-node-authentication.md @@ -0,0 +1,39 @@ +--- +description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control." +sidebar_label: "Beacon node authentication" +slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication +--- + +# Beacon node authentication + +## HTTP Basic Access Authentication + +If you want to use Charon with an [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic ` where `Authorization` will be the header key and `Basic ` will be the header value. The `` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`. + +:::warning +These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node. +::: + +## Usage example + +Suppose we have an HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command: + +``` +echo -n "john:doe" | base64 +``` + +Then you could pass the flag to your Charon instance like this: + +``` +charon run --beacon-node-headers="Authorization=Basic am9objpkb2U=" +``` + +Or you could specify it as an environment variable like this: + +``` +CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U=" +``` + +:::info +Note that 'Authorization' is followed with an `=` rather than the usual `:`. +::: diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/client-swap.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/client-swap.md new file mode 100644 index 0000000000..cc32615ab1 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/client-swap.md @@ -0,0 +1,174 @@ +--- +description: "Swap EL, CL, VC and MEV clients in the stack." +sidebar_label: "Client Swap" +slug: /advanced-and-troubleshooting/advanced/client-swap +--- + +# Client swap + +If you are using CDVN, the default stack is: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | --------- | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | + +However, to achieve greater resilience through client diversity, it is preferred to run a variety of clients across your cluster, ideally ensuring no single EL/CL/VC runs on one third of the nodes or more. CDVN supports changing from the default clients. + +Currently supported client options are: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | ------------ | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | +| | Grandine | | Nimbus | Commit boost | +| | | | Prysm | | +| | | | Teku | | + +For support between different combinations, refer to Charon's compatibility matrix, found in the [prepare section of the docs](../../run-a-dv/prepare/how_where_dvs.md) or under [release notes](https://github.com/ObolNetwork/charon/releases/) for each release. + +:::info +As CDVN natively supports more clients, the number of possible combinations grows quickly. +We test extensively, but cannot guarantee the performance of all possible client combos. +If you run a mixed-client cluster, monitor performance and be ready to swap to another client if you observe issues. +::: + +## Choosing clients in fresh cluster + +In order to choose which clients to use in a new cluster, simply leave uncommented (only) the desired `EL`, `CL`, `MEV` or `VC` variables in the `.env` file. There must be only one client per component. The cluster will use the respective client for each component. + +## Swapping clients in an already running cluster + +:::warning +For ([L](https://github.com/obolNetwork/lido-charon-distributed-validator-node))[CDVN](https://github.com/obolNetwork/charon-distributed-validator-node) users who created their `.env` file before the release of charon `v1.7.0`, there are breaking changes between then and the current multi-client `.env` file setup. +The minimal addition to an older version of the `.env` file compatible with the current versions of the repos is to add `COMPOSE_PROFILES=el_nethermind,cl_lighthouse,dv_charon,vc_lodestar,mev_mevboost` to your existing `.env` file. +Some environment variables were renamed in order to be client-agnostic. **If you had set these environment variables to custom values in your `.env`, you need to set the new variables to your custom values**. They serve the same purpose. + +| Old | New | +|-------------------------------|--------------------------------- | +| NETHERMIND_PORT_P2P | EL_PORT_P2P | +| NETHERMIND_IP_HTTP | EL_IP_HTTP | +| NETHERMIND_PORT_HTTP | EL_PORT_HTTP | +| NETHERMIND_IP_ENGINE | EL_IP_ENGINE | +| NETHERMIND_PORT_ENGINE | EL_PORT_ENGINE | +| LIGHTHOUSE_PORT_P2P | CL_PORT_P2P | +| LODESTAR_PORT_METRICS | VC_PORT_METRICS | +| MEVBOOST_TIMEOUT_GETHEADER | MEV_TIMEOUT_GETHEADER | +| MEVBOOST_TIMEOUT_GETPAYLOAD | MEV_TIMEOUT_GETPAYLOAD | +| MEVBOOST_TIMEOUT_REGVAL | MEV_TIMEOUT_REGVAL | +| MEVBOOST_RELAYS | MEV_RELAYS | +| NETHERMIND_PROMTAIL_MONITORED | EL_NETHERMIND_PROMTAIL_MONITORED | +| LIGHTHOUSE_PROMTAIL_MONITORED | CL_LIGHTHOUSE_PROMTAIL_MONITORED | +| LODESTAR_PROMTAIL_MONITORED | VC_LODESTAR_PROMTAIL_MONITORED | +| MEV_BOOST_PROMTAIL_MONITORED | MEV_MEV_BOOST_PROMTAIL_MONITORED | + +::: + +1. Copy the new `.env.sample.` file to `.env`. +2. Comment or uncomment your preferred Execution, Consensus, Validator, and MEV clients and save the file. +3. Stop the existing cluster that uses the old environment file. + +```sh +docker compose --profile "" down +``` + +3. Start the node again to pick up the changes to the `.env` file. + +```sh +docker compose up -d +``` + +Your node should start up with the new clients. + +### Swap Consensus layer + +:::info +The code snippets under those steps are assuming you are swapping from Lighthouse CL to Grandine CL and you. +::: + +1. Stop the existing consensus layer client container. + +:::info +If you do not want to experience downtime while the new beacon node is syncing, you can set a fallback beacon node for Charon (`CHARON_FALLBACK_BEACON_NODE_ENDPOINTS` env variable) that will be used while the new BN is syncing. +Note that you need to restart Charon as well in order for it to take effect. +::: + +```sh +docker compose down cl-lighthouse +``` + +1. Comment out the currently set `CL` environment variable in `.env` (i.e.: `CL=cl-lighthouse` -> `#CL=cl-lighthouse`). Uncomment the desired CL (i.e.: `#CL=cl-grandine` -> `CL=cl-grandine`). + +2. Start the new consensus layer client container. + +```sh +docker compose up cl-grandine -d +``` + +4. Restart Charon in order to update the CL client it's querying. + +```sh +docker compose down charon +docker compose up charon -d +``` + +5. After the new consensus layer client is synced and you are assured the new setup is working, you can delete the previous CL client's data in order to save resources. + +```sh +rm -rf ./data/lighthouse +``` + +### Swap Validator client + +:::info +The code snippets under those steps are assuming you are swapping from Lodestar VC to Teku VC. +::: + +1. Stop the existing validator client container. + +```sh +docker compose down vc-lodestar +``` + +2. Comment out the currently set `VC` environment variable in `.env` (i.e.: `VC=vc-lodestar` -> `#VC=vc-lodestar`). Uncomment the desired VC (i.e.: `#VC=vc-teku` -> `VC=vc-teku`). + +3. Start the new validator client container. + +```sh +docker compose up vc-teku -d +``` + +4. After the new validator client is started and you are assured the new setup is working, you can delete the previous VC's data in order to save resources + +```sh +rm -rf ./data/lodestar +``` + +### SWAP MEV client + +:::info +The code snippets under those steps are assuming you are swapping from MEV Boost to Commit Boost and you are using Lighthouse CL. +::: + +:::info +If switching to Commit Boost, you will need to copy a Commit Boost TOML config `commit-boost/config.toml.sample.` to `commit-boost/config.toml`, as it does not support `.env` configurations yet. Make sure the configuration matches what you have had set for mev-boost, in terms of relays and timeouts. +::: + +1. Stop the existing MEV client container. + +```sh +docker compose down mev-mevboost +``` + +2. Comment out the currently set `MEV` environment variable in `.env` (i.e.: `MEV=mev-mevboost` -> `#MEV=mev-mevboost`). Uncomment the desired MEV (i.e.: `#MEV=mev-commitboost` -> `MEV=mev-commitboost`). + +3. Start the new MEV client container. + +```sh +docker compose up mev-commitboost -d +``` + +4. Restart the beacon node in order to update the MEV it's querying. + +```sh +docker compose down cl-lighthouse +docker compose up cl-lighthouse -d +``` diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..cb8e916119 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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](https://docs.obol.org/next/learn/intro/launchpad). + +### Pre-requisites[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#pre-requisites) {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#install-the-package) {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#instantiate-the-client) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#propose-the-cluster) {#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. + +```sh +// 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#invite-the-operators-to-complete-the-dkg) {#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](https://docs.obol.org/next/learn/intro/launchpad) to complete the process + +1. Operators navigate to `https://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](https://docs.obol.org/next/run/start/quickstart_group) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#retrieve-the-created-distributed-validators-using-the-sdk) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#activate-the-dvs-using-the-deposit-contract) {#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. + +```sh +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[​](https://docs.obol.org/next/adv/advanced/quickstart-sdk#usage-examples) {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/custom-graffiti.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/custom-graffiti.md new file mode 100644 index 0000000000..567abf7ad0 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/custom-graffiti.md @@ -0,0 +1,20 @@ +--- +description: "Add custom graffiti to your block proposals" +sidebar_label: "Custom Graffiti" +slug: /advanced-and-troubleshooting/advanced/custom-graffiti +--- + +# Custom Graffiti + +By default, Charon adds a `charon/-` graffiti to all block proposals. This can be customized using the `--graffiti` and `--graffiti-disable-client-append` CLI flags. + +The `--graffiti` flag accepts either: + +* A single string, which will be used by all validators, or +* A comma-separated list of strings, allowing each validator to have a unique graffiti (one string per validator). + +When possible, Charon automatically appends an Obol signature (`OB`) and the specific consensus client type used (``) to the end of the custom graffiti. This behavior can be disabled by setting the `--graffiti-disable-client-append` flag. + +:::info +The graffiti field in block proposals has a maximum size of 32 bytes. +::: diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..f7e0c6e6de --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#getting-started-with-charon--the-builder-api) {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#client-configuration) {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#charon) {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#consensus-clients) {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](https://docs.obol.org/next/run/prepare/test-command#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#validator-clients) {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured[​](https://docs.obol.org/next/adv/advanced/quickstart-builder-api#verify-your-cluster-is-correctly-configured) {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [Ultrasound Relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. If you are using [Titan Relay](https://titanrelay.xyz), you can check their API by running `curl https://titanrelay.xyz/relay/v1/data/validator_registration?pubkey=0x123..456` with the public key of a validator in your cluster. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/enable-tls-protocol.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/enable-tls-protocol.md new file mode 100644 index 0000000000..c822a27225 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/enable-tls-protocol.md @@ -0,0 +1,37 @@ +--- +description: "Enable the TLS protocol to secure HTTPS requests made by the Validator Client to Charon." +sidebar_label: "Enable TLS Protocol" +slug: /advanced-and-troubleshooting/advanced/enable-tls-protocol +--- + +# Enable TLS protocol + +## Securing VC to Charon communication + +To secure the communication between the Validator Client and Charon, you can enable the TLS protocol in Charon's HTTP server. This only affects [Beacon API](https://ethereum.github.io/beacon-APIs/) endpoints and not debug/metrics endpoints. As an operator of the node, you need to have a TLS certificate and a private key that signed this certificate or CSR. Then you need to configure Charon to use them. +## Usage example + +Suppose we don't have a TLS certificate and a key yet. We can create a self-signed certificate and a key using OpenSSL: + +``` +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +Then you could pass the flags to your Charon instance like this: + +``` +charon run --vc-tls-cert-file cert.pem --vc-tls-key-file key.pem +``` + +Charon accepts a certificate in PEM or CRT formats and the private key in PEM or DER formats. + +Also you can specify these parameters as environment variables like this: + +``` +CHARON_VC_TLS_CERT_FILE="cert.pem" +CHARON_VC_TLS_KEY_FILE="key.pem" +``` + +On the Validator Client (VC) side, no additional configuration is typically required. The VC will automatically use the TLS protocol when communicating with Charon. However, if the TLS certificate is signed by a custom or non-standard certificate authority (CA), you may need to configure the VC to trust this CA. This can usually be achieved by adding the CA's certificate to the trusted certificate store on the machine running the VC. + +If necessary, you can also enable `insecure` mode in the VC configuration to bypass TLS verification. Note that this approach is not recommended for production environments as it compromises security. Detailed instructions for configuring specific Validator Clients are beyond the scope of this article. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md new file mode 100644 index 0000000000..7f301659c6 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md @@ -0,0 +1,13 @@ +--- +description: "Add fallback beacon nodes to use when primary beacon node fails" +sidebar_label: "Fallback Beacon Nodes" +slug: /advanced-and-troubleshooting/advanced/fallback-beacon-nodes +--- + +# Fallback beacon nodes + +Charon allows specifying multiple beacon node URL endpoints. It sends requests to all specified endpoints simultaneously and proceeds with the first response received. This approach improves reliability but increases the load on the beacon nodes. + +To mitigate this additional load, Charon supports configuring a fallback list of beacon nodes. These fallback nodes are only used if all primary beacon nodes fail to respond. This allows operators to designate less critical or public beacon nodes as a backup option, without impacting them under normal conditions. + +To configure fallback beacon nodes, provide a comma-separated list of beacon node URLs using the `--fallback-beacon-node-endpoints` CLI flag. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/nicknames.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/nicknames.md new file mode 100644 index 0000000000..9606a46788 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/nicknames.md @@ -0,0 +1,18 @@ +--- +description: "Add a nickname to your Charon node" +sidebar_label: "Nicknames" +slug: /advanced-and-troubleshooting/advanced/nicknames +--- + +# Nicknames + +By default, Charon assigns each node a name by combining a random adjective with a random name from a predefined list. While these names are human-readable, they are not easily memorable or personalised for operators. + +You can set a personalised nickname for your Charon node by using the `--nickname` CLI flag followed by the desired string. This nickname is shared with other Charon nodes in the same cluster and included as a label in your Prometheus metrics. + +Nicknames can serve various purposes, such as providing a more memorable identifier, including a Discord ID for alerting, or adding a website URL for publicity. + + + + + diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/operator-rotation.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/operator-rotation.md new file mode 100644 index 0000000000..7296cff819 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/operator-rotation.md @@ -0,0 +1,112 @@ +--- +description: "Validator consolidation workflow for rotating operators in an Obol distributed validator cluster." +sidebar_label: "Operator Rotation" +slug: /advanced-and-troubleshooting/advanced/operator-rotation +--- + +# Operator Rotation + +### Introduction to Operator Rotation using Pectra Validator Consolidation + +Validator consolidation is a new feature for the Ethereum network, introduced with the last **Pectra** network upgrade. It allows a user to "consolidate" multiple validators into a single, new validator. + +- Consolidations can only be performed when the source validator has 0x01 or 0x02 withdrawal credentials and the target validator must be 0x02. The consolidation transaction must be sent from the withdrawal address defined in the source credentials. The target withdrawal credentials can be any address of choice. +- This process transfers the staked ETH from the old validators to the new one while the stake never leaves the beacon chain. The only partial downtime for the source validator is the standard 27-hour waiting period on the beacon chain before the withdrawal. When compared to fully exiting and re-depositing, consolidation avoids the sweep delay required in that option. + +> [!NOTE] +> Future direction (in development): We’re building toward full cluster mutability so operators can react quickly to real-world events. That includes resharing fresh key material across the cluster if there’s ever a security concern, adding new operators to reach full Byzantine fault tolerance, and removing operators who aren’t meeting performance expectations. The goal is to make these changes possible without exiting or consolidating validators. The forthcoming tooling will guide the cluster through a coordinated workflow and produce a fresh set of operator files ready for cutover when you’re comfortable switching over. +--- + +### Guide: Operator Rotation in an Obol Cluster via Validator Consolidation + +Validator consolidation enables a safe and efficient way to perform operator rotation in an Obol cluster. This is achieved by transferring staked ETH directly from a **source cluster** (source validators with its original operators) to a **target cluster** (target validators with a new set of operators). Operator rotation can be classified into several different scenarios: + +- Source and target cluster validators have the same withdrawal address that is an EOA (wallet address) or a Safe contract. +- Source and target cluster validators have different withdrawal addresses but they are still EOAs. +- Source and target cluster validators have the same OVMs as withdrawal addresses. +- Source and target cluster validators have different OVMs as withdrawal addresses. Source can be an OVM and withdrawal can be an EigenPod/EOA/Safe or vice versa. + +In this guide, we focus on source and target validators that have the same withdrawal address that is an EOA or Safe. The other scenarios are actively in development. + +**Pros:** + +- Compared to the Charon native operator rotation, which requires technical knowledge of node operation, must be executed by operators, and is risky for key security when not done properly, consolidation-based operator rotation can be performed by a withdrawal address (who can be a non-operator such as an ETH allocator). +- Very minimal downtime of ~27 hours (256 epochs) on the stake with source validators. Missed rewards are estimated to be around 0.00296 ETH per validator. + +**Cons:** + +- If the number of validators is very high, even a single day of downtime (even though small) can add up. +- Target validators need to be active. This requires an additional 32 ETH for each target validator the cluster wishes to set up. + +This document outlines the step-by-step process for rotating operators in an Obol DVT cluster using the new validator consolidation feature. This guide assumes you are starting with a source cluster with four existing operators and want to consolidate their validators into a new target cluster with four new operators. + +### 1. Prepare the Target Cluster + +- **Create a New Cluster:** As the user, first create a new Obol cluster for four new operators of your choice. More details can be found [here](https://docs.obol.org/run-a-dv/start/create-a-dv-with-a-group). +- **Set Withdrawal Address:** Set the withdrawal address for this new cluster to be the same EOA address you used for the source cluster. In future this can be changed to a withdrawal address of your choice. +- **Deploy a New Splitter:** Deploy a new splitter contract dedicated to the new operators of the target cluster. +- **Configure Validators:** Ensure the validators in the new cluster are configured as **compounding validators** with the `0x02` credential type. To enable this make sure to turn the compound toggle on or use the `--compounding` flag if using the CLI directly. + +![Compounding validator configuration](/img/gitbook/operator-rotation-compounding.png) + +- **Run Nodes:** Start the Charon nodes for all operators in the new target cluster. Make sure all the nodes are healthy and ready for deposits. More details [here](https://docs.obol.org/run-a-dv/running/monitoring). +- **Activate Validators:** Activate the target validators by depositing 32 ETH for each. More details [here](https://docs.obol.org/run-a-dv/running/activate-a-dv). The image shows a new operator `0x493...9b1`. + +![Target validator activation view](/img/gitbook/operator-rotation-activate.png) + +### 2. Finalize the Source Cluster + +- Have a source cluster ready. Make sure you are connected with the correct withdrawal address. In this case, the operator [`0x28eC4c075DF60535DDE5e2788C34B1961c99474c`](https://hoodi.launchpad.obol.org/operator/0x28eC4c075DF60535DDE5e2788C34B1961c99474c/) is also the withdrawal address. + +![Source cluster withdrawal operator](/img/gitbook/operator-rotation-source-withdrawal.png) + +![Source cluster validator list](/img/gitbook/operator-rotation-source-dashboard.png) + +- **Distribute Rewards:** Before proceeding, distribute all pending rewards from the source cluster's splitter contract to ensure all financial obligations are settled with the original operators. The rewards should be 0 after rewards are distributed and claimed. + +![Splitter rewards distribution](/img/gitbook/operator-rotation-rewards.png) + +### 3. Initiate the Consolidation + +- **Access the Migration Tool:** Navigate to the Obol Launchpad migration page by using a URL such as `https://hoodi.launchpad.obol.org/migrate/?withdrawalAddress=your_withdrawal_address`. Alternatively, click the **Migrate** button on a target validator's page within the target cluster dashboard. This **Migrate** button is only clickable for validators where the connected address is the withdrawal address. Make sure the correct address is connected. + +![Launchpad migrate action](/img/gitbook/operator-rotation-migrate.png) + +- **Select Validators:** On the migration page, select the source validators from the original cluster that you wish to consolidate. + + + +- **Confirm and Consolidate:** Click the **Migrate** button to send the consolidation request. + + +![Target withdrawal address view](/img/gitbook/operator-rotation-target-withdrawal.png) + +### 4. Post-Consolidation Actions + +> [!INFO] +> Screenshots are for reference only, your validator balances and performance will differ. + +- **Source Validator Exit:** Once the consolidation request is processed by the Ethereum network, the source validators will be set to exit automatically. On [beaconcha.in](https://beaconcha.in) the validator pubkey will show an **exiting** status with consolidation in progress. + +![Beaconcha.in validator showing exiting status](/img/gitbook/operator-rotation-beaconcha-exiting.png) + +![Launchpad validator exit notification](/img/gitbook/operator-rotation-launchpad-exit.png) + +- **Waiting Period:** After the exit is complete, the validator enters a ~27 hour waiting period (256 epochs). In the example below the validator is marked **exited** while the withdrawable epoch remains in the future (43257). Once the withdrawable epoch is reached, ETH will be consolidated to the target validator. + +![Beaconcha.in withdrawable epoch countdown](/img/gitbook/operator-rotation-beaconcha-withdrawable.png) + +- **ETH Transfer:** After the waiting period, the staked ETH from the source validators is automatically consolidated and credited to the target validators in the new cluster. + +![Target validator credited after consolidation](/img/gitbook/operator-rotation-target-credited.png) + +- **Wind Down Source Clusters:** Once the source validators have fully exited and funds have settled with the target cluster, you can wind down the original operators. + +![Cluster dashboard ready for wind down](/img/gitbook/operator-rotation-wind-down.png) + +This process ensures a seamless and secure operator rotation, leveraging the efficiency of validator consolidation to minimize downtime and avoid a lengthy manual withdrawal process. + +**Example clusters used in screenshots:** + +- Target cluster: [0x15d1…9e32](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x15d113c8c3e3ca1ec24bbdd5c5d8f9065c36f07d9d70c13e9a4efba8a35b9e32) +- Source cluster: [0xF321…2885](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0xF321443022ABA165FF5635CF71DC9DA0FC29EE91D03117055E97A1F92B5C2885) diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..49cafc2463 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.7.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. +::: diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..8ce77f2e94 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,110 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +:::info +Starting with Charon v1.7.0, you may not need to manually prepare the keystore files as described below. Charon can recursively search for keystore files in the specified directory and attempt to match the corresponding password files. The only case where this does not work is when you specify an exact list of withdrawal addresses; in that case, you must prepare the files manually and ensure the keystore indices match the order of the specified withdrawal addresses. +::: + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.7.0 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet \ + --publish +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..8c80d667f8 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,38 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency and decentralization, you can opt to host your own relay on a separate open and static internet port. + +```shell +# Figure out your public IP +curl v4.ident.me + +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your public IPv4 or DNS hostname + +nano relay/docker-compose.yml + +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +Note that a local `relay/.charon/charon-enr-private-key` file will be created next to `relay/docker-compose.yml` to ensure a persisted relay ENR across restarts. + +A list of publicly available relays that can be used is maintained [here](../security/risks.md). diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/README.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/README.md new file mode 100644 index 0000000000..08d9fd5147 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Security" +slug: /advanced-and-troubleshooting/security +--- + +# security + diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/bug-bounty.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/bug-bounty.md new file mode 100644 index 0000000000..06a57d0d34 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/bug-bounty.md @@ -0,0 +1,181 @@ +--- +description: "Bug Bounty Policy" +sidebar_label: "Obol Bug Bounty Program" +slug: /advanced-and-troubleshooting/security/bug-bounty +--- + +# Obol Bug Bounty Program + +## Overview + +At Obol Labs, we prioritize the security of our distributed validator software and related services. Our Bug Bounty Program is designed to encourage and reward security researchers for identifying and reporting potential vulnerabilities. This initiative supports our commitment to the security and integrity of our products. + +## Participant Eligibility + +Participants must meet the following criteria to be eligible for the Bug Bounty Program: + +- Not reside in countries where participation in such programs is prohibited. +- Be at least 14 years of age and possess the legal capacity to participate. +- Have received consent from your employer, if applicable. +- Not have been employed or contracted by Obol Labs, nor be an immediate family member of an employee, within the last 12 months. + +## Scope of the Program + +Eligible submissions must involve software and services developed by Obol, specifically under the domains of: + +- Charon the DV Middleware Client +- Obol DV Launchpad and Public API +- Obol Splits Contracts +- Obol Labs hosted Public Relay Infrastructure + +Submissions related to the following are considered out of scope: + +- Social engineering +- Rate Limiting (Non-critical issues) +- Physical security breaches +- Non-security related UX/UI issues +- Third-party application vulnerabilities +- The [Obol](https://obol.org) static website or the Obol infrastructure +- The operational security of node operators running or using Obol software + +## Program Rules + +- Submitted bugs must not have been previously disclosed publicly. +- Only first reports of vulnerabilities will be considered for rewards; previously reported or known vulnerabilities are ineligible. +- The severity of the vulnerability, as assessed by our team, will determine the reward amount. See the "Rewards" section for details. +- Submissions must include a reproducible proof of concept. +- The Obol security team reserves the right to determine the eligibility and reward for each submission. +- Program terms may be updated at Obol's discretion. +- Valid bugs may be disclosed to partner protocols within the Obol ecosystem to enhance overall security. + +## Rewards Structure + +Rewards are issued based on the severity and impact of the disclosed vulnerability, determined at the discretion of Obol Labs. + +### Critical Vulnerabilities: Up to $100,000 + +A Critical-level vulnerability is one that has a severe impact on the security of the in-production system from an unauthenticated external attacker, and requires immediate attention to fix. Highly likely to have a material impact on validator private key security, and/or loss of funds. + +- High impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully exfiltrate BLS (not K1) private key material from a threshold number of operators in the cluster. +- Attacker that is not a member of the cluster can achieve the production of arbitrary BLS signatures from a threshold number of operators in the cluster. +- Attacker can craft a malicious cluster invite capable of subverting even careful review of all data to steal funds during a deposit. +- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield +- Direct loss of funds +- Permanent freezing of funds (fix requires hard fork) +- Network not being able to confirm new transactions (Total network shutdown) +- Protocol insolvency + +### High Vulnerabilities: Up to $10,000 + +For significant security risks that impact the system from a position of low-trust and require a significant effort to fix. + +- High impact, medium likelihood +- Medium impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully partition the cluster and keep the cluster offline indefinitely. +- Attacker that is not a member of the cluster can exfiltrate Charon ENR private keys. +- Attacker that is not a member of the cluster can destroy funds but cannot steal them. +- Unintended chain split (Network partition) +- Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments +- RPC API crash affecting projects with greater than or equal to 25% of the market capitalization on top of the respective layer +- Theft of unclaimed yield +- Theft of unclaimed royalties +- Permanent freezing of unclaimed yield +- Permanent freezing of unclaimed royalties +- Temporary freezing of funds +- Retrieve sensitive data/files from a running server: + - blockchain keys + - database passwords + - (this does not include non-sensitive environment variables, open source code, or usernames) +- Taking state-modifying authenticated actions (with or without blockchain state interaction) on behalf of other users without any interaction by that user, such as: + - Changing cluster information + - Withdrawals + - Making trades + +### Medium Vulnerabilities: Up to $2,500 + +For vulnerabilities with a moderate impact, affecting system availability or integrity. + +- High impact, low likelihood +- Medium impact, medium likelihood +- Low impact, high likelihood + +Impacts: + +- Attacker that is a member of a cluster can exfiltrate K1 key material from another member. +- Attacker that is a member of the cluster can denial of service attack enough peers in the cluster to prevent operation of the validator(s) +- Attacker that is a member of the cluster can bias the protocol in a manner to control the majority of block proposal opportunities. +- Attacker can get a DV Launchpad user to inadvertently interact with a smart contract that is not a part of normal operation of the launchpad. +- Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours +- Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network +- Charon cluster identity private key theft +- Rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle +- Charon public relay node is compromised and leads to cluster topologies getting discovered and disrupted +- Smart contract unable to operate due to lack of token funds +- Block stuffing +- Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol) +- Theft of gas +- Unbounded gas consumption +- Redirecting users to malicious websites (Open Redirect) + +### Low Vulnerabilities: Up to $500 + +For vulnerabilities with minimal impact, unlikely to significantly affect system operations. + +- Low impact, medium likelihood +- Medium impact, low likelihood + +Impacts: + +- Attacker can sometimes put a Charon node in a state that causes it to drop one out of every one hundred attestations made by a validator +- Attacker can display bad data on a non-interactive part of the launchpad. +- Contract fails to deliver promised returns, but doesn't lose value +- Shutdown of greater than 10% or equal to but less than 30% of network processing nodes without brute force actions, but does not shut down the network +- Changing details of other users (including modifying browser local storage) without already-connected wallet interaction and with significant user interaction such as: + - Iframing leading to modifying the backend/browser state (must demonstrate impact with PoC) +- Taking over broken or expired outgoing links such as: + - Social media handles, etc. +- Temporarily disabling user to access target site, such as: + - Locking up the victim from login + - Cookie bombing, etc. + +Rewards may be issued as cash, merchandise, or other forms of recognition, at Obol's discretion. Only one reward will be granted per unique vulnerability. + +## The following activities are prohibited by this bug bounty program + +- Any testing on mainnet or public testnet deployed code; all testing should be done on local-forks of either public testnet or mainnet +- Any testing with pricing oracles or third-party smart contracts +- Attempting phishing or other social engineering attacks against our employees and/or customers +- Any testing with third-party systems and applications (e.g. browser extensions) as well as websites (e.g. SSO providers, advertising networks) +- Any denial of service attacks that are executed against project assets +- Automated testing of services that generate significant amounts of traffic +- Public disclosure of an unpatched vulnerability in an embargoed bounty + +## Submission process + +To report a vulnerability, please contact us at security@obol.tech with: + +- A detailed description of the vulnerability and its potential impact. +- Steps to reproduce the issue. +- Any relevant proof of concept code, screenshots, or documentation. +- Your contact information. + +Incomplete reports may not be eligible for rewards. + +## Disclosure and Confidentiality + +Obol Labs will disclose vulnerabilities and the identity of the researcher (with consent) after remediation. Researchers are required to maintain confidentiality until official disclosure by Obol Labs. + +## Legal and Ethical Compliance + +Participants must adhere to all relevant laws and regulations. Obol Labs will not pursue legal action against researchers reporting vulnerabilities in good faith, but reserves the right to respond to violations of this policy. + +## Non-Disclosure Agreement (NDA) + +Participants may be required to sign an NDA for access to certain proprietary information during their research. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/contact.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/contact.md new file mode 100644 index 0000000000..0b4b54d4fd --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/contact.md @@ -0,0 +1,11 @@ +--- +description: "Security details for the Obol Network" +sidebar_label: "Contacts" +slug: /advanced-and-troubleshooting/security/contact +--- + +# Contacts + +Please email security@obol.tech to report a security incident, vulnerability, bug or inquire about Obol's security. + +Also, visit the [obol security repo](https://github.com/ObolNetwork/obol-security) for more details. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/ev-assessment.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/ev-assessment.md new file mode 100644 index 0000000000..969839bde3 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/ev-assessment.md @@ -0,0 +1,293 @@ +--- +description: "Software Development Security Assessment" +sidebar_label: "Software Development at Obol" +slug: /advanced-and-troubleshooting/security/ev-assessment +--- + +# Software Development at Obol + +When hardening a project's technical security, team member's operational security, and the security of the software development practices in use by the team are some of the most critical areas to secure. Many hacks and compromises in the space to date have been a result of these attack vectors rather than exploits of the software itself. + +With this in mind, in January 2023 the Obol team retained the expertise of Ethereal Venture's security researcher Alex Wade; to interview key stakeholders and produce a report into the team's Software Development Lifecycle. + +The below page is a result of the report that was produced. What is present here has had some sensitive information redacted, and contains responses to the recommendations made, detailing the actions the Obol team have taken to mitigate what has been highlighted. + +## Obol Report + +**Prepared by: Alex Wade (Ethereal Ventures)** **Date: Jan 2023** + +Over the past month, I worked with Obol to review their software development practices in preparation for their upcoming security audits. My goals were to review and analyze: + +* Software development processes +* Vulnerability disclosure and escalation procedures +* Key personnel risk + +The information in this report was collected through a series of interviews with Obol’s project leads. + +## Contents + +* Background Info +* Analysis - Cluster Setup and DKG + * Key Risks + * Potential Attack Scenarios +* Recommendations + * R1: Users should deploy cluster contracts through a known on-chain entry point + * R2: Users should deposit to the beacon chain through a pool contract + * R3: Raise the barrier to entry to push an update to the Launchpad +* Additional Notes + * Vulnerability Disclosure + * Key Personnel Risk + +## Background Info + +**Each team lead was asked to describe Obol in terms of its goals, objectives, and key features.** + +### What is Obol? + +Obol builds DVT (Distributed Validator Technology) for Ethereum. + +### What is Obol’s goal? + +Obol’s goal is to solve a classic distributed systems problem: uptime. + +Rather than requiring Ethereum validators to stake on their own, Obol allows groups of operators to stake together. Using Obol, a single validator can be run cooperatively by multiple people across multiple machines. + +In theory, this architecture provides validators with some redundancy against common issues: server and power outages, client failures, and more. + +### What are Obol’s objectives? + +Obol’s business objective is to provide base-layer infrastructure to support a distributed validator ecosystem. As Obol provides base layer technology, other companies and projects will build on top of Obol. + +Obol’s business model is to eventually capture a portion of the revenue generated by validators that use Obol infrastructure. + +### What is Obol’s product? + +Obol’s product consists of three main components, each run by its own team: a webapp, a client, and smart contracts. + +* [DV Launchpad](../../learn/intro/launchpad.md): A webapp to create and manage distributed validators. +* [Charon](../../learn/charon/intro.md): A middleware client that enables operators to run distributed validators. +* [Solidity](../../learn/intro/obol-splits.md): Withdrawal and fee recipient contracts for use with distributed validators. + +## Analysis - Cluster Setup and DKG + +The Launchpad guides users through the process of creating a cluster, which defines important parameters like the validator’s fee recipient and withdrawal addresses, as well as the identities of the operators in the cluster. In order to ensure their cluster configuration is correct, users need to rely on a few different factors. + +**First, users need to trust the Charon client** to perform the DKG correctly, and validate things like: + +* Config file is well-formed and is using the expected version +* Signatures and ENRs from other operators are valid +* Cluster config hash is correct +* DKG succeeds in producing valid signatures +* Deposit data is well-formed and is correctly generated from the cluster config and DKG. + +However, Charon’s validation is limited to the digital: signature checks, cluster file syntax, etc. It does NOT help would-be operators determine whether the other operators listed in their cluster definition are the real people with whom they intend to start a DVT cluster. So - + +**Second, users need to come to social consensus with fellow operators.** While the cluster is being set up, it’s important that each operator is an active participant. Each member of the group must validate and confirm that: + +* the cluster file correctly reflects their address and node identity, and reflects the information they received from fellow operators +* the cluster parameters are expected – namely, the number of validators and signing threshold + +**Finally, users need to perform independent validation.** Each user should perform their own validation of the cluster definition: + +* Is my information correct? (address and ENR) +* Does the information I received from the group match the cluster definition? +* Is the ETH2 deposit data correct, and does it match the information in the cluster definition? +* Are the withdrawal and fee recipient addresses correct? + +These final steps are potentially the most difficult, and may require significant technical knowledge. + +## Key Risks + +### 1. Validation of Contract Deployment and Deposit Data Relies Heavily on Launchpad + +From my interviews, it seems that the user deploys both the withdrawal and fee recipient contracts through the Launchpad. + +What I’m picturing is that during the first parts of the cluster setup process, the user is prompted to sign one or more transactions deploying the withdrawal and fee recipient contracts to mainnet. The Launchpad apparently uses an npm package to deploy these contracts: `0xsplits/splits-sdk`, which I assume provides either JSON artifacts or a factory address on chain. The Launchpad then places the deployed contracts into the cluster config file, and the process moves on. + +If an attacker has published a malicious update to the Launchpad (or compromised an underlying dependency), the contracts deployed by the Launchpad may be malicious. The questions I’d like to pose are: + +* How does the group creator know the Launchpad deployed the correct contracts? +* How does the rest of the group know the creator deployed the contracts through the Launchpad? + +My understanding is that this ultimately comes down to the independent verification that each of the group’s members performs during and after the cluster’s setup phase. + +At its worst, this verification might consist solely of the cluster creator confirming to the others that, yes, those addresses match the contracts I deployed through the Launchpad. + +A more sophisticated user might verify that not only do the addresses match, but the deployed source code looks roughly correct. However, this step is far out of the realm of many would-be validators. To be really certain that the source code is correct would require auditor-level knowledge. + +The risk is that: + +* the deployed contracts are NOT the correctly-configured 0xsplits waterfall/fee splitter contracts +* most users are ill-equipped to make this determination themselves +* we don’t want to trust the Launchpad as the single source of truth + +In the worst case, the cluster may end up depositing with malicious withdrawal or fee recipient credentials. If unnoticed, this may net an attacker the entire withdrawal amount, once the cluster exits. + +Note that the same (or similar) risks apply to validation of deposit data, which has the potential to be similarly difficult. I’m a little fuzzy on which part of the Obol stack actually generates the deposit data / deposit transaction, so I can’t speak to this as much. However, I think the mitigation for both of these is roughly the same - read on! + +**Mitigation:** + +It’s certainly a good idea to make it harder to deploy malicious updates to the Launchpad, but this may not be entirely possible. A higher-yield strategy may be to educate and empower users to perform independent validation of the DVT setup process - without relying on information fed to them by Charon and the Launchpad. + +I’ve outlined some ideas for this in #R1 and #R2. + +### 2. Social Consensus, aka “Who sends the 32 ETH?” + +Depositing to the beacon chain requires a total of 32 ETH. Obol’s product allows multiple operators to act as a single validator together, which means would-be operators need to agree on how to fund the 32 ETH needed to initiate the deposit. + +It is my understanding that currently, this process comes down to trust and loose social consensus. Essentially, the group needs to decide who chips in what amount together, and then trust someone to take the 32 ETH and complete the deposit process correctly (without running away with the money). + +Granted, the initial launch of Obol will be open only to a small group of people as the kinks in the system get worked out - but in preparation for an eventual public release, the deposit process needs to be much simpler and far less reliant on trust. + +Mitigation: See #R2. + +**Potential Attack Scenarios** + +During the interview process, I learned that each of Obol’s core components has its own GitHub repo, and that each repo has roughly the same structure in terms of organization and security policies. For each repository: + +* There are two overall github organization administrators, and a number of people have administrative control over individual repositories. +* In order to merge PRs, the submitter needs: + * CI/CD checks to pass + * Review from one person (anyone at Obol) + +Of course, admin access also means the ability to change these settings - so repo admins could theoretically merge PRs without needing checks to pass, and without review/approval, organization admins can control the full GitHub organization. + +The following scenarios describe the impact an attack may have. + +**1. Publishing a malicious version of the Launchpad, or compromising an underlying dependency** + +* Reward: High +* Difficulty: Medium-Low + +As described in Key Risks, publishing a malicious version of the Launchpad has the potential to net the largest payout for an attacker. By tampering with the cluster’s deposit data or withdrawal/fee recipient contracts, an attacker stands to gain 32 ETH or more per compromised cluster. + +During the interviews, I learned that merging PRs to main in the Launchpad repo triggers an action that publishes to the site. Given that merges can be performed by an authorized Obol developer, this makes the developers prime targets for social engineering attacks. + +Additionally, the use of the `0xsplits/splits-sdk` NPM package to aid in contract deployment may represent a supply chain attack vector. It may be that this applies to other Launchpad dependencies as well. + +In any case, with a fairly large surface area and high potential reward, this scenario represents a credible risk to users during the cluster setup and DKG process. + +See #R1, #R2, and #R3 for some ideas to address this scenario. + +**2. Publishing a malicious version of Charon to new operators** + +* Reward: Medium +* Difficulty: High + +During the cluster setup process, Charon is responsible both for validating the cluster configuration produced by the Launchpad, as well as performing a DKG ceremony between a group’s operators. + +If new operators use a malicious version of Charon to perform this process, it may be possible to tamper with both of these responsibilities, or even get access to part or all of the underlying validator private key created during DKG. + +However, the difficulty of this type of attack seems quite high. An attacker would first need to carry out the same type of social engineering attack described in scenario 1 to publish and tag a new version of Charon. Crucially, users would also need to install the malicious version - unlike the Launchpad, an update here is not pushed directly to users. + +As long as Obol is clear and consistent with communication around releases and versioning, it seems unlikely that a user would both install a brand-new, unannounced release, and finish the cluster setup process before being warned about the attack. + +**3. Publishing a malicious version of Charon to existing validators** + +* Reward: Low +* Difficulty: High + +Once a distributed validator is up and running, much of the danger has passed. As a middleware client, Charon sits between a validator’s consensus and validator clients. As such, it shouldn’t have direct access to a validator’s withdrawal keys nor signing keys. + +If existing validators update to a malicious version of Charon, it’s likely the worst thing an attacker could theoretically do is slash the validator, however, assuming Charon has no access to any private keys, this would be predicated on one or more validator clients connected to Charon also failing to prevent the signing of a slashable message. In practice, a compromised Charon client is more likely to pose liveness risks than safety risks. + +This is not likely to be particularly motivating to potential attackers - and paired with the high difficulty described above, this scenario seems unlikely to cause significant issues. + +## Recommendations + +### R1: Users should deploy cluster contracts through a known on-chain entry point + +During setup, users should only sign one transaction via the Launchpad - to a contract located at an Obol-held ENS (e.g. `launchpad.obol.eth`). This contract should deploy everything needed for the cluster to operate, like the withdrawal and fee recipient contracts. It should also initialize them with the provided reward split configuration (and any other config needed). + +Rather than using an NPM library to supply a factory address or JSON artifacts, this has the benefit of being both: + +* **Harder to compromise:** as long as the user knows launchpad.obol.eth, it’s pretty difficult to trick them into deploying the wrong contracts. +* **Easier to validate** for non-technical users: the Obol contract can be queried for deployment information via etherscan. For example:\ + ![](/img/gitbook/image-50.png) + +Note that in order for this to be successful, Obol needs to provide detailed steps for users to perform manual validation of their cluster setups. Users should be able to treat this as a “checklist:” + +* Did I send a transaction to `launchpad.obol.eth`? +* Can I use the ENS name to locate and query the deployment manager contract on etherscan? +* If I input my address, does etherscan report the configuration I was expecting? + * withdrawal address matches + * fee recipient address matches + * reward split configuration matches + +As long as these steps are plastered all over the place (i.e. not just on the Launchpad) and Obol puts in effort to educate users about the process, this approach should allow users to validate cluster configurations themselves - regardless of Launchpad or NPM package compromise. + +**Obol’s response** + +Roadmapped: add the ability for the OWR factory to claim and transfer its reverse resolution ownership. + +### R2: Users should deposit to the beacon chain through a pool contract + +Once cluster setup and DKG is complete, a group of operators should deposit to the beacon chain by way of a pool contract. The pool contract should: + +* Accept Eth from any of the group’s operators +* Stop accepting Eth when the contract’s balance hits (32 ETH \* number of validators) +* Make it easy to pull the trigger and deposit to the beacon chain once the critical balance has been reached +* Offer all of the group’s operators a “bail” option at any point before the deposit is triggered + +Ideally, this contract is deployed during the setup process described in #R1, as another step toward allowing users to perform independent validation of the process. + +Rather than relying on social consensus, this should: + +* Allow operators to fund the validator without needing to trust any single party +* Make it harder to mess up the deposit or send funds to some malicious actor, as the pool contract should know what the beacon deposit contract address is + +**Obol’s response** + +Roadmapped: give the operators a streamlined, secure way to deposit Ether (ETH) to the beacon chain collectively, satisfying specific conditions: + +* Pooling from multiple operators. +* Ceasing to accept ETH once a critical balance is reached, defined by 32 ETH multiplied by the number of validators. +* Facilitating an immediate deposit to the beacon chain once the target balance is reached. +* Provide a 'bail-out' option for operators to withdraw their contribution before initiating the group's deposit to the beacon chain. + +### R3: Raise the barrier to entry to push an update to the Launchpad + +Currently, any repo admin can publish an update to the Launchpad unchecked. + +Given the risks and scenarios outlined above, consider amending this process so that the sole compromise of either admin is not sufficient to publish to the Launchpad site. It may be worthwhile to require both admins to approve publishing to the site. + +Along with simply adding additional prerequisites to publish an update to the Launchpad, ensure that both admins have enabled some level of multi-factor authentication on their GitHub accounts. + +**Obol’s response** + +We removed individual’s ability to merge changes without review, enforced MFA, signed commits, and employed Bulldozer bot to make sure a PR gets merged automatically when all checks pass. + +## Additional Notes + +### Vulnerability Disclosure + +During the interviews, I got some conflicting information when asking about Obol’s vulnerability disclosure process. + +Some interviewees directed me towards Obol’s security repo, which details security contacts: [ObolNetwork/obol-security](https://github.com/ObolNetwork/obol-security), while some answered that disclosure should happen primarily through Immunefi. While these may both be part of the correct answer, it seems that Obol’s disclosure process may not be as well-defined as it could be. Here are some notes: + +* I wasn’t able to find information about Obol on Immunefi. I also didn’t find any reference to a security contact or disclosure policy in Obol’s docs. +* When looking into the obol security repo, I noticed broken links in a few of the sections in README.md and SECURITY.md: + * Security policy + * More Information +* Some of the text and links in the Bug Bounty Program don’t seem to apply to Obol (see text referring to Vaults and Strategies). +* The Receiving Disclosures section does not include a public key with which submitters can encrypt vulnerability information. + +It’s my understanding that these items are probably lower priority due to Obol’s initial closed launch - but these should be squared away soon! \[Obol response to latest vuln disclosure process goes here] + +**Obol’s response** + +we addressed all of the concerns in the obol-security repository: + +1. The security policy link has been fixed +2. The Bug Bounty program received an overhaul and clearly states rewards, eligibility, and scope +3. We list two GPG public keys for which we accept encrypted vulnerabilities reports. + +We are actively working towards integrating Immunefi in our security pipeline. + +### Key Personnel Risk + +A final section on the specifics of key personnel risk faced by Obol has been redacted from the original report. Particular areas of control highlighted were github org ownership and domain name control. + +**Obol’s response** + +These risks have been mitigated by adding an extra admin to the github org, and by setting up a second DNS stack in case the primary one fails, along with general Opsec improvements. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/overview.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/overview.md new file mode 100644 index 0000000000..d56083987f --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/overview.md @@ -0,0 +1,38 @@ +--- +description: "Security Overview" +sidebar_label: "Overview" +slug: /advanced-and-troubleshooting/security/overview +--- + +# Overview + +This page serves as an overview of the Obol Network from a security point of view. + +This page is updated quarterly. The last update was on 2024-June-19. + +## Table of Contents + +* [Overview](overview.md) + * [Table of Contents](overview.md#table-of-contents) + * [List of Security Audits and Assessments](overview.md#list-of-security-audits-and-assessments) + * [Security focused documents](overview.md#security-focused-documents) + * [Bug Bounty](overview.md#bug-bounty) + +## List of Security Audits and Assessments + +The completed audits reports are linked [here](https://github.com/ObolNetwork/obol-security/tree/main/audits). + +* A review of Obol Labs [development processes](./ev-assessment.md) by [Ethereal Ventures](https://www.etherealventures.com/). +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/) resulting in version [`v0.16.0`](https://github.com/ObolNetwork/charon/releases/tag/v0.16.0). +* A second [assessment of Charon](https://obol.tech/charon_quantstamp_assessment.pdf) by [QuantStamp](https://quantstamp.com/) resulting in version [`v0.19.1`](https://github.com/ObolNetwork/charon/releases/tag/v0.19.1). +* A [solidity audit](./smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* A [penetration testing certificate](https://github.com/ObolNetwork/obol-security/blob/main/audits/Sayfer_2024-03_Penetration_Testing_CFD.pdf) of the Obol DV Launchpad by [Sayfer](https://sayfer.io/). +* A second [solidity audit](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V2%20Audit%20-%20Nethermind.pdf) by [Nethermind](https://nethermind.io). + +## Security focused documents + +* A [threat model](./threat_model.md) for a DV middleware client like Charon. + +## Bug Bounty + +Information related to disclosing bugs and vulnerabilities to Obol can be found on [the next page](bug-bounty.md). diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/risks.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/risks.md new file mode 100644 index 0000000000..46d2302a3d --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/risks.md @@ -0,0 +1,53 @@ +--- +description: "Outlining potential centralization risks and their mitigations" +sidebar_label: "Centralization Risks and Mitigation" +slug: /advanced-and-troubleshooting/security/risks +--- + +# Centralization Risks and Mitigation + +## Risk: Obol hosting the relay infrastructure + +**Mitigation**: Self-host a relay. + +One of the risks associated with Obol hosting the [LibP2P relays](../../learn/charon/charon-networking.md) infrastructure allowing peer discovery is that if Obol-hosted relays go down, peers won't be able to discover each other and perform the DKG. To mitigate this risk, external organizations and node operators can consider self-hosting a relay. This way, if Obol's relays go down, the clusters can still operate through other relays in the network. Ensure that all nodes in the cluster use the same relays, or they will not be able to find each other if they are connected to different relays. + +The following non-Obol entities run relays that you can consider adding to your cluster (you can have more than one per cluster, see the `--p2p-relays` flag of [`charon run`](../../learn/charon/charon-cli-reference.md#the-run-command)): + +| Entity | Relay URL | +| ------------------------------------------- | ------------------------------------ | +| [DSRV](https://www.dsrvlabs.com/) | https://charon-relay.dsrvlabs.dev | +| [Infstones](https://infstones.com/) | https://obol-relay.infstones.com/ | +| [Hashquark](https://www.hashquark.io/) | https://relay-2.prod-relay.721.land/ | +| [Figment](https://figment.io/) | https://relay-1.obol.figment.io/ | +| [Node Guardians](https://nodeguardians.io/) | https://obol-relay.nodeguardians.io/ | + +## Risk: Obol being able to update Charon code + +**Mitigation**: Pin specific docker versions or compile from source on a trusted commit. + +Another risk associated with Obol is the Labs team having the ability to update the [Charon code](https://github.com/ObolNetwork/charon) used by node operators within DV clusters, which could introduce vulnerabilities or malicious code. To mitigate this risk, operators can consider pinning specific versions or hashes of the Docker image or git repo commits that have been [thoroughly tested](overview.md#list-of-security-audits-and-assessments) and accepted by the network. This would ensure that any updates are carefully vetted and reviewed by the community, and only introduced into a running cluster gradually. The labs team will strive to communicate the security or operational impact any Charon update entails, giving operators the chance to decide whether they want potential performance or quality of experience improvements, or whether they remain on a trusted version for longer. + +## Risk: Obol hosting the DV Launchpad + +**Mitigation**: Use [`create cluster`](../../learn/charon/charon-cli-reference.md#the-create-command) or [`create dkg`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) locally and distribute the files manually. + +Hosting the first Charon frontend, the [DV Launchpad](../../learn/intro/launchpad.md), on a centralized server could create a single point of failure, as users would have to rely on Obol's server to access the protocol. This could limit the decentralization of the protocol and could make it vulnerable to attacks or downtime. Obol hosting the launchpad on a decentralized network, such as IPFS would be a first step but not enough. This is why the Charon code is source-available and contains a CLI interface to interact with the protocol locally. + +To mitigate the risk of launchpad failure, consider using the `create cluster` or `create dkg` commands locally and distributing the key shares files manually. + +## Risk: Obol custodying pre-signed exit messages + +**Mitigation**: Use withdrawal address initiated exits or validator client exits + +Before the Pectra hardfork, there was no way for a delegator to exit their validator without the co-operation of the node operator(s). In an effort to reduce this risk, Obol developed the [Charon exit](../../learn/charon/charon-cli-reference.md#the-exit-command) command, which allows operators to pre-sign and download exit messages to give to the delegator for safe keeping, ensuring they could broadcast them at any point in time. This feature relies on Obol's [API](../../api/what-is-this-api), and means the Obol core team could in theory initiate an unwanted exit. If a delegator does not want to be exposed to that centralization risk, they should not use Charon's built-in exit commands, and instead should initiate exits using the [EIP7002](https://eips.ethereum.org/EIPS/eip-7002) exit contract, or alternatively by running normal exit commands on the operator's validator clients. + +Guides to exiting validators using all three approaches are outlined [here](../../run-a-dv/running/exit-a-dv.mdx). + +## Risk: Obol going bust/rogue + +**Mitigation**: Use key recovery. + +The final centralization risk associated with Obol is the possibility of the company going bankrupt or acting maliciously, which could lead to a loss of confidence in the Charon client. To mitigate this risk, Obol has implemented a key reconstitution mechanism. This would allow the clusters to continue operating and to (re)create full validator private keys suitable for standard staking setups even if Obol is no longer able or willing to provide support. + +A guide to recombine key shares into a single private key can be accessed [here](../advanced/quickstart-combine.md). diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/smart-contract-audit.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/smart-contract-audit.md new file mode 100644 index 0000000000..c23023dd88 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/smart-contract-audit.md @@ -0,0 +1,467 @@ +--- +sidebar_label: "Smart Contract Audit" +slug: /advanced-and-troubleshooting/security/smart-contract-audit +--- + +# Smart Contract Audit + +## Obol Audit Report: Obol Manager Contracts + +Prepared by: Zach Obront, Independent Security Researcher + +Date: Sept 18 to 22, 2023 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2023%20-%20Obol%20Splits%20V1%20Audit%20-%20Zach%20Obront.pdf) + +### About **Obol**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-obol) {#about-obol} +The Obol Network is an ecosystem for trust minimized staking that enables people to create, test, run & co-ordinate distributed validators. + +The Obol Manager contracts are responsible for distributing validator rewards and withdrawals among the validator and node operators involved in a distributed validator. + +### About **zachobront**[​](https://docs.obol.org/next/adv/security/smart_contract_audit#about-zachobront) {#about-zachobront} +Zach Obront is an independent smart contract security researcher. He serves as a Lead Senior Watson at Sherlock, a Security Researcher at Spearbit, and has identified multiple critical severity bugs in the wild, including in a Top 5 Protocol on Immunefi. You can say hi on Twitter at [@zachobront](http://twitter.com/zachobront). + +### Summary & Scope[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary--scope) {#summary--scope} +The [ObolNetwork/obol-manager-contracts](https://github.com/ObolNetwork/obol-manager-contracts/) repository was audited at commit [50ce277919723c80b96f6353fa8d1f8facda6e0e](https://github.com/ObolNetwork/obol-manager-contracts/tree/50ce277919723c80b96f6353fa8d1f8facda6e0e). + +The following contracts were in scope: + +* src/controllers/ImmutableSplitController.sol +* src/controllers/ImmutableSplitControllerFactory.sol +* src/lido/LidoSplit.sol +* src/lido/LidoSplitFactory.sol +* src/owr/OptimisticWithdrawalReceiver.sol +* src/owr/OptimisticWithdrawalReceiverFactory.sol + +After completion of the fixes, the [2f4f059bfd145f5f05d794948c918d65d222c3a9](https://github.com/ObolNetwork/obol-manager-contracts/tree/2f4f059bfd145f5f05d794948c918d65d222c3a9) commit was reviewed. After this review, the updated Lido fee share system in [PR #96](https://github.com/ObolNetwork/obol-manager-contracts/pull/96/files) (at commit [fd244a05f964617707b0a40ebb11b523bbd683b8](https://github.com/ObolNetwork/obol-splits/pull/96/commits/fd244a05f964617707b0a40ebb11b523bbd683b8)) was reviewed. + +### Summary of Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#summary-of-findings) {#summary-of-findings} +| Identifier | Title | Severity | Fixed | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------- | ----- | +| [M-01](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) | Future fees may be skirted by setting a non-ETH reward token | Medium | ✓ | +| [M-02](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) | Splits with 256 or more node operators will not be able to switch on fees | Medium | ✓ | +| [M-03](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) | In a mass slashing event, node operators are incentivized to get slashed | Medium | | +| [L-01](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) | Obol fees will be applied retroactively to all non-distributed funds in the Splitter | Low | ✓ | +| [L-02](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) | If OWR is used with rebase tokens and there's a negative rebase, principal can be lost | Low | ✓ | +| [L-03](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) | LidoSplit can receive ETH, which will be locked in contract | Low | ✓ | +| [L-04](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) | Upgrade to latest version of Solady to fix LibClone bug | Low | ✓ | +| [G-01](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) | stETH and wstETH addresses can be saved on implementation to save gas | Gas | ✓ | +| [G-02](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) | OWR can be simplified and save gas by not tracking distributedFunds | Gas | ✓ | +| [I-01](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) | Strong trust assumptions between validators and node operators | Informational | | +| [I-02](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) | Provide node operator checklist to validate setup | Informational | | + +### Detailed Findings[​](https://docs.obol.org/next/adv/security/smart_contract_audit#detailed-findings) {#detailed-findings} +#### \[M-01] Future fees may be skirted by setting a non-ETH reward token[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) {#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token} +Fees are planned to be implemented on the `rewardRecipient` splitter by updating to a new fee structure using the `ImmutableSplitController`. + +It is assumed that all rewards will flow through the splitter, because (a) all distributed rewards less than 16 ETH are sent to the `rewardRecipient`, and (b) even if a team waited for rewards to be greater than 16 ETH, rewards sent to the `principalRecipient` are capped at the `amountOfPrincipalStake`. + +This creates a fairly strong guarantee that reward funds will flow to the `rewardRecipient`. Even if a user were to set their `amountOfPrincipalStake` high enough that the `principalRecipient` could receive unlimited funds, the Obol team could call `distributeFunds()` when the balance got near 16 ETH to ensure fees were paid. + +However, if the user selects a non-ETH token, all ETH will be withdrawable only thorugh the `recoverFunds()` function. If they set up a split with their node operators as their `recoveryAddress`, all funds will be withdrawable via `recoverFunds()` without ever touching the `rewardRecipient` or paying a fee. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation) + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept) + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-1) + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-1) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed[​](https://docs.obol.org/next/adv/security/smart_contract_audit#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendations) + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-2) + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-2) + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-3) + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-3) + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-4) + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-1) + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-4) + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-5) + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug[​](https://docs.obol.org/next/adv/security/smart_contract_audit#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#proof-of-concept-2) + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-5) + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-6) + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-6) + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-7) + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds[​](https://docs.obol.org/next/adv/security/smart_contract_audit#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#recommendation-7) + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-8) + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-01-strong-trust-assumptions-between-validators-and-node-operators) {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-9) + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup[​](https://docs.obol.org/next/adv/security/smart_contract_audit#i-02-provide-node-operator-checklist-to-validate-setup) {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review**[**​**](https://docs.obol.org/next/adv/security/smart_contract_audit#review-10) + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\ diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..1e557a58a5 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,155 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritise the liveness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalise operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator. A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..1ed84c4d89 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# troubleshooting + diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..3db41c89d8 --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,298 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting any other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +For now, ENR rotation/replacement is not supported, it will be supported in a future release. Therefore, it's advised to always keep a backup of your `charon-enr-private-key ` in a secure location (ex: cloud storage, USB Flash drive, etc.). + +### I can't find the keys anywhere +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows. +Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + + +## Lighthouse + + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + + +### Lighthouse gives the error `not enough time for a discovery search` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance. +Using 3rd-party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Can't connect to Beacon API` + +If you are running EL and CL outside Obol on the same machine, you might need to open ports in your firewall to allow connections incoming from the docker instance. +In order to know the IP of the docker network, run: +`docker network inspect ` + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is +probably not online to sign successfully. Make sure all operators are +running the latest version of Charon. To check if some peers are not online: +`docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key +should be created and placed in the right directory during the ceremony. +Also, make sure you are working in the right directory: +`charon-distributed-validator-node`. + +### `Failed to confirm node connection` +Wait for Teku & Lighthouse sync to be complete. + + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum +limit has been reached. This is most often due to "maximum reservations per IP/peer". +This is when your Charon node is restarting or in some error loop and constantly +attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it. +This should allow the relay enough time to reset your IP/peer limits and +should then allow new reservations. This could also be due to the relay +being overloaded in general, so reaching a server wide "maximum connections" +limit. This is an issue with relay scalability and we are working in a long +term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO_RESERVATION (204)` indicates the peer +isn't connected to the relay, so the the Charon client cannot connect to the +peer via the relay. That might be because the peer is offline or the peer is +configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact +same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when +it failed to fetch the required data from the beacon node API. This indicates +a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +attestation data. This indicates the associated attestation duty failed to obtain +a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed due to no partial v2 committee subscription submitted by the cluster +validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to insufficient +partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to no partial randao +signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This +could indicate that insufficient honest peers participated in consensus or p2p +network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted +by the local validator client. This could indicate that the local validator client +is offline, or has connection problems with Charon, or has some other problem. +See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database +as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was +received from any peer. This indicates all peers are offline or p2p network connection +problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures +for the duty was received from peers. This indicates problems with peers or p2p +network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient +partial signatures failed. This indicates inconsistent signed data. This indicates +a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it +checks for a special file called the private key lock file. This file has the +same name as the ENR private key file but with a `.lock` extension. +If the private key lock file exists and is not older than 5 seconds, Charon won't +run. It doesn't allow running multiple Charon instances with the same ENR private +key. If the private key lock file has a timestamp older than 5 seconds, Charon +will replace it and continue with its work. If you`re sure that no other Charon +instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the +validators private key shares don't match the ENR private key. There may +have been a mix-up during deployment, leading to a mismatching validator +client key share index. + +For example: Imagine node N is Alice, and node M is Bob, the error would read: +` mismatching validator client key share index, Bob's key share submitted to Alice's charon node ` +Bob's private key share(s) are imported to a VC that is connected to +Alice's Charon node. This is an invalid setup/deployment. +Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside +cluster-lock.json and see that matches with the public key inside +`node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data the first time. +You can solve this by following the steps below: +- Click the Wheel Icon > Datasources. +- Click prometheus. +- Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +- Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel +Can be linked to a Teku keystore issue. + + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + You can ignore this error unless you have been contacted by the Obol Team + with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. + + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly +on Linux and WSL for Windows systems. In the interest of security, the +charon docker image runs as a non-root user, and this user often does not +have the permissions to write in the directory you have checked out the code +to. This can be generally be fixed with some of the following: +- Running docker commands with `sudo`, if you haven't [set up docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +- Changing the permissions of the `.charon` folder with the commands: + - `mkdir .charon` (if it doesn't already exist); + - `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + It`s because both Nethermind and Lighthouse start syncing and so there's + connectivity issues among the containers. Simply let the containers run for + a while. You won't observe frequent errors when Nethermind finishes syncing. You + can also add a second beacon node endpoint for something like Infura by + adding a comma separated API URL to the end of + `CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. + +### How do I fix the `plugin "loki" not found` error? + If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + + +## Relay + +### ` Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the +relay/docker-compose.yml with your real public IP or DNS hostname. + +### ` Timeout resolving bootnode ENR: context deadline exceeded` +The relay you are trying to connect to your peers via is offline or +unreachable. + diff --git a/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..83d3f55c5e --- /dev/null +++ b/versioned_docs/version-v1.7/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or uncontactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.7/api/address.mdx b/versioned_docs/version-v1.7/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.7/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.7/api/cluster-definition.mdx b/versioned_docs/version-v1.7/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.7/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.7/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.7/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..4da8ad1bcc --- /dev/null +++ b/versioned_docs/version-v1.7/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Effectiveness + + diff --git a/versioned_docs/version-v1.7/api/cluster-lock.mdx b/versioned_docs/version-v1.7/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.7/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.7/api/dv-exit.mdx b/versioned_docs/version-v1.7/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.7/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.7/api/metrics.mdx b/versioned_docs/version-v1.7/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.7/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.7/api/owr-information.mdx b/versioned_docs/version-v1.7/api/owr-information.mdx new file mode 100644 index 0000000000..0e20b4892a --- /dev/null +++ b/versioned_docs/version-v1.7/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR + + diff --git a/versioned_docs/version-v1.7/api/state.mdx b/versioned_docs/version-v1.7/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.7/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.7/api/system.mdx b/versioned_docs/version-v1.7/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.7/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.7/api/techne-credentials.mdx b/versioned_docs/version-v1.7/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.7/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.7/api/terms-and-conditions.mdx b/versioned_docs/version-v1.7/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..d5d32a5dba --- /dev/null +++ b/versioned_docs/version-v1.7/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TermsAndConditions + + + + diff --git a/versioned_docs/version-v1.7/api/what-is-this-api.md b/versioned_docs/version-v1.7/api/what-is-this-api.md new file mode 100644 index 0000000000..6951dbffbb --- /dev/null +++ b/versioned_docs/version-v1.7/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://launchpad.obol.org), a dApp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API can also be used via the [Obol-SDK](../sdk/index.md). + +Read more about Obol and how to use the [launchpad](https://launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.7/community-and-governance/community/README.md b/versioned_docs/version-v1.7/community-and-governance/community/README.md new file mode 100644 index 0000000000..c8d5f1c1b9 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# community + diff --git a/versioned_docs/version-v1.7/community-and-governance/community/grants-program/README.md b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/README.md new file mode 100644 index 0000000000..5d369cab6b --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/README.md @@ -0,0 +1,62 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/community/grants-program +--- + +# Grants Program + +We are excited to launch the **Obol Grants Program**. After a successful pilot wave that supported several meaningful initiatives, we’re doubling down on our commitment to ecosystem growth. + +If you're curious about what we funded in the past, check out our [Grants Pilot Wrap-Up blog post](https://blog.obol.org/grants-program-pilot-wave-report-pilot-phase-wrap-up/). It includes full context and direct links to our Questbook portal where you can browse the funded projects and on-chain disbursement records. + +*** + +## Purpose {#purpose} +The Obol Grants Program supports projects that advance the strategic goals of the Obol. The goal is to: + +* Provide milestone-based funding to **builders** aligned with our goals +* Offer a standardized and permissionless framework for **educators and event organizers** to run impactful Obol-focused community events & workshops +* Enable technical contributors to pick up **open-source missions** from our backlog + +This program exists to extend the reach of the Collective: helping us ship faster, strengthen adoption of Distributed Validators (DVs), other important Obol technology, and empower contributors globally. + +## Structure {#structure} +The Grants Program is organized into **three distinct Grant Tracks:** + +### [Staking Mastery Program](grants-track-for-staking-masters.md) {#staking-mastery-program} +* For contributors applying to work on any of the [Obol Collective 2025 SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388) +* This track revives the original Staking Mastery Program. I will now be running on a rolling basis to support research and technical contributions that advance distributed staking +* Open application process with milestone-based disbursement + +### [Community Events & Workshops](grants-track-for-community-events.md) {#community-events-and-workshops} +* For anyone hosting Obol-focused workshops, meetups or onboarding sessions +* Permissionless structure, funded retroactively based on proof of attendance and impact + +### [Open Strategic Missions](grants-track-for-open-strategic-missions/strategic-open-missions.md) {#open-strategic-missions} +* Pre-scoped, technical tasks created by Obol +* Contributors can apply to complete these missions for funding + +:::danger +Before applying, make sure to check the detailed sub-page for each grant track by clicking on its title above. These pages outline specific requirements, proof formats, and payout logic for each track. +::: + +## Review Timeline {#review-timeline} +All submitted applications (regardless of track) will receive an initial response within **7 business days**, with one of the following statuses: + +* ✅ **Accepted** — You’re good to start +* ❌ **Declined** — Not aligned with our current priorities +* 💬 **Needs Discussion** — We’d like to refine scope, budget, or timeline with you + +## Funding & Disbursement {#funding-and-disbursement} +* All grants are scoped and approved with a fixed amount in $OBOL, agreed upon upfront. +* Disbursements are made in **OBOL tokens**, disbursed upon approval of each milestone +* Payments can be **one-shot** or broken into **milestones**, depending on scope + +## Transparency & Communication {#transparency-and-communication} +* Every funded grant will be published publicly on **Questbook along with the detailed milestones and on-chain funding transactions.** You can find links to the relevant Questbook pages for each grant track in their dedicated sub-pages. +* Projects will be highlighted periodically through: +* Obol’s official social channels (Twitter, Discord) +* Grant recap blog posts & newsletters +* Grantees may be asked to publish short public recaps for visibility + +_**Ready to get started? You can learn more about each track by visiting the dedicated pages.**_ diff --git a/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-community-events.md b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-community-events.md new file mode 100644 index 0000000000..fd622dde5a --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-community-events.md @@ -0,0 +1,123 @@ +--- +sidebar_label: "Grants Track for Community Events" +slug: /community-and-governance/community/grants-program/grants-track-for-community-events +--- + +# Grants Track for Community Events + +This track supports permissionless, retroactive funding for Obol-focused local events, workshops, and onboarding sessions focused on Distributed Validators. + +The goal is to empower community leaders to grow Obol on the ground, with a clear and standardized support model. + +You can explore all supported events on [Questbook](https://questbook.app/dashboard/?grantId=68d793dd306fa3a0a64b83c2\&chainId=10). + +*** + +## Overview, Eligibility and Scope {#overview-eligibility-and-scope} +This track is designed to support **community-led educational events and workshops** that are **entirely focused on Obol Distributed Validators (DVs)**. These events should serve to onboard new participants, educate existing ones, and help expand the reach of Obol on the ground. + +To ensure consistency and predictability, this track uses a **permissionless framework** for supporting events with **up to 100 attendees.** Larger events may still be supported, but require prior coordination. + +Funding is available for two types of outcomes: + +1. **The event itself** — covering costs related to the event venue, food and beverages. +2. S**uccessful conversions to Obol DVs** — when attendees go on to spin up Distributed Validators using Obol technology, the event host or operators may qualify for a bonus reward. + +All events must: + +* Be **fully centered on Obol DVs** +* Be **submitted with the required proofs** to unlock retroactive funding upon verification +* Be limited to **100 participants or fewer** for automatic eligibility + +## Budget & Funding {#budget-and-funding} +### 🍕 1. Food & Drink Budget (Event Support) {#id-1.-food-and-drink-budget-event-support} +To help cover the costs of hosting, we provide **up to $15 per verified attendee**, retroactively, upon proof of the event. This amount includes the event venue, food, drinks, and minor operational expenses. + +* This support is **capped at 100 attendees per event.** +* Verification requirements are listed in the next section (“Submission Process”). + +### 🧪 2. TVS Conversion Bonus (Net New Stake Incentive) {#id-2.-tvs-conversion-bonus-net-new-stake-incentive} +To reward tangible ecosystem growth, we offer a **0.1% bonus of the total net new TVS (Total Value Staked)** attributable to your event. + +* Only **Obol-based DV clusters** are eligible. +* The **conversion must clearly follow from the event**, with proof submitted and verified. +* Bonus payouts will be made **monthly** over a **12-month period**, so long as the validators remain active. + +:::tip +For example, if your event led to the launch of 5 validators totaling 160 ETH (≈$640K TVS with ETH at $4000), you could be eligible for a $640 bonus, distributed over 12 months (\~$53.33/month), assuming validators remain online and performing. +::: + +This structure is designed to: + +* Ensure **sustainable staking growth**, not just one-time deposits +* Protect against potential **farming or gaming** of the bonus system +* Reward contributors for **long-term value creation** in the network + +:::danger +All budgets will be denominated in USD for clarity, and payments will be made in OBOL token equivalents at the time of disbursement. +::: + +:::tip +Want to estimate your potential TVS Conversion Bonus? Use this [simulator](https://bonus.gcp.obol.tech/) to adjust the ETH price and number of validators and preview your expected monthly rewards. +::: + +_The TVS conversion bonus will be paid directly to the operator who submits the form and verifies their validator address. It is then up to them to decide if or how they wish to share this bonus with the event organizer or other contributors. The Obol Association reserves the right to modify the bonus structure or reward calculation method at any time for future submissions. Any bonuses already approved and in-progress will remain unchanged and honored as agreed._ + +## Submission Process {#submission-process} +The Community Events track uses a simple **three-step submission flow**. Only one of them is optional, the rest are required for funding. + +### 1. [Pre-Event Form (optional but recommended)](https://forms.gle/Y5LTpEkF3TThRNUo9) {#id-1.-pre-event-form-optional-but-recommended} +We encourage hosts to fill out a short form **ahead of their event** to let the Association know what’s being planned. While not mandatory, this step allows us to: + +* Coordinate on visibility and cross-post the event on official channels +* Offer lightweight guidance or connections if needed +* Ensure the event fits within the scope of this grant track + +### 2. [Post-Event Submission (required for pizza & food budget)](https://forms.gle/MRZEaX3DtSZe9jSK7) {#id-2.-post-event-submission-required-for-pizza-and-food-budget} +After the event, hosts must fill out a **proof-of-event** form to unlock retroactive funding. This submission must include: + +* A **public tweet thread** summarizing the event ↳ Must highlight Obol DVs and mention @ObolCollective +* A **group photo** from the event, with clear timestamp and the organizer present +* Any **slides or presentation materials** used during the event +* A link to the **Luma page (or equivalent)** used for RSVPs ↳ Must include attendee list +* **Receipts** (food/beverage/venue) matching the number of participants + +_**Once submitted, your application will be reviewed and — if approved — disburse the food & drink budget (up to $15/attendee, max 100 attendees).**_ + +### 3. [TVS Conversion Bonus Submission (required for validator conversion bonus)](https://forms.gle/cmz5uw6cCwM5pZi96) {#id-3.-tvs-conversion-bonus-submission-required-for-validator-conversion-bonus} +There’s no deadline here, submit any time after the event once validators are live. To unlock your **TVS Conversion Bonus**, we require to fill the dedicated form with: + +* A submission from one of the **validator operators**, including: + * **Ethereum address** used to run the validator (to prove ownership) + * **Details of the Distributed Validator cluster** (to verify it was launched post-event) + * **Statement of correlation** explaining how the event led to this onboarding +* Follow-up confirmation from the **event organizer** +* A **public recap** from the host listing the validators or clusters onboarded via the event + +_**Once submitted, your application will be reviewed and — if approved — we will distribute the TVS bonus (0.1% of net new TVS distributed over 12 months).**_ + +## Evaluation & Review {#evaluation-and-review} +For **each of the three forms submitted** (pre-event intent, post-event proof, or TVS conversion bonus), Obol will respond within **seven open business days** with one of the following: + +* ✅ **Accepted** +* ❌ **Rejected** +* 💬 **Needs additional information** + +Once post-event materials have been reviewed and accepted, the host will be asked to **submit the final version of the application to Questbook**, including: + +* A summary of the event +* Final verified participant count +* Funding amount (e.g. food & drink budget) + +This Questbook submission will serve as the **source of truth for transparency and on-chain funding**. + +:::tip +If a validator conversion bonus is approved at a later date, it will be logged as a second milestone under the same Questbook grant and funded accordingly. +::: + +## Expectations & Visibility {#expectations-and-visibility} +We want to **showcase and amplify** meaningful contributions from the community. + +* If the event was flagged in advance via the optional pre-event form, we may help promote it via **Obol's official social media channels**, including social media and/or Discord. +* Once an event has been successfully validated and funded, it will be included in **periodic blog posts or funding recap threads.** +* We strongly encourage hosts to post their own event recaps publicly on X (Twitter) and **tag @ObolCollective** to boost visibility of their work and highlight the role of DVs in the broader staking ecosystem. diff --git a/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md new file mode 100644 index 0000000000..05db384572 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md @@ -0,0 +1,74 @@ +--- +sidebar_label: "Grants Track for Open Strategic Missions" +slug: /community-and-governance/community/grants-program/grants-track-for-open-strategic-missions +--- + +# Grants Track for Open Strategic Missions + +This track enables technical contributors to pick up pre-scoped missions designed by the Obol team. + +These missions are ideal for developers looking to ship meaningful tooling or infrastructure improvements for the DV ecosystem. + +To view active and completed missions, visit [Questbook](https://questbook.app/dashboard/?grantId=68d79449306fa3a0a64b88e9\&chainId=10). + +*** + +## Overview, Eligibility and Scope {#overview-eligibility-and-scope} +This track enables technical contributors to pick up **pre-scoped missions** designed by the Obol team. + +These missions are ideal for developers looking to ship meaningful tooling, research, or infrastructure improvements for **Obol Distributed Validators.** + +These missions are published directly in the [section below](strategic-open-missions.md). Each mission outlines: + +* The scope of work +* The deliverables expected +* The funding offered +* Context and materials + +This track is open to: + +* Independent developers and small technical teams +* Individuals with proven experience in Ethereum staking, especially Distributed Validators + +Our goal is to reduce internal backlog by collaborating with technically proficient external contributors who want to build meaningful tooling, integrations, or research for the Obol ecosystem. + +## Budget & Funding {#budget-and-funding} +Each mission comes with a proposed **budget offer.** These grants follow a **milestone-based payment** model: + +* Milestones are defined up front as part of the mission spec or during onboarding +* Funding is disbursed **only after milestone completion is validated** + +If adjustments are needed to the scope or funding, these will be clarified before the contributor starts work. + +## Submission Process {#submission-process} +Anyone interested in picking up a mission must fill out a [short application form](https://forms.gle/SgUx4n7hAZ28JpY47). It will request: + +* Name of the mission +* Background and relevant experience of the applicant(s) +* Relevant GitHub links or previous work +* Optional: Questions or additional clarification requests + +Only after submitting this form and receiving explicit approval may a contributor begin work. + +## Evaluation & Review {#evaluation-and-review} +Once an application form is submitted, Obol will provide a first response within **seven open business days**, which will be one of the following: + +1. ✅ **Accepted**: The contributor is cleared to begin work +2. ❌ **Rejected**: The contributor is not a fit or the mission is already taken +3. 💬 **Further discussion required**: Additional alignment on scope, timeline, or budget is needed + +:::danger +If you begin work without approval, we reserve the right to decline funding even if the work is completed. +::: + +## Expectations & Visibility {#expectations-and-visibility} +Contributors to this grant track will be expected to: + +* Provide milestone updates or completion summaries +* Be open to publishing public recaps or demos + +In return, Obol will: + +* Highlight completed missions on social channels +* Include them in quarterly reports and blog posts +* Provide visibility to help contributors build reputation diff --git a/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md new file mode 100644 index 0000000000..b3387e6593 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md @@ -0,0 +1,77 @@ +--- +sidebar_label: "Strategic Open Missions" +slug: /community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions +--- + +# Strategic Open Missions + +To view ongoing and completed missions, visit [Questbook](https://questbook.app/dashboard/?grantId=68d79449306fa3a0a64b88e9\&chainId=10). + +This section will serve as the **central hub** for all currently available open missions under the Staking Mastery Program. + +* It will be updated regularly with new missions +* Completed missions will be archived +* Funded missions will be trackable via our Questbook hub + +Please check back soon for available missions. + +If you have a technical mission you'd like to propose to Obol instead, please use the [Staking Masters Grants track](../grants-track-for-staking-masters.md). + +*** + +## Open Strategic Missions {#open-strategic-missions} +This section lists specific, high-impact technical initiatives Obol has decided to open to external contributors. These are projects that contribute meaningfully to the Obol Distributed Validators (DVs) and we welcome applications from individuals or teams with the right expertise. + +Each mission includes a pre-defined scope and fixed budget. All applications are reviewed on a case-by-case basis. + +:::danger +All Open Missions must go through the official application and evaluation process before work begins. Milestone-based funding is tracked via Questbook and paid upon approval. +::: + +## 🟢 Open for Application {#open-for-application} +### Add Validator Feature in DappNode {#add-validator-feature-in-dappnode} +**Goal**: Implement the add-validator functionality into the Obol DappNode package, leveraging the existing docs as reference. + +🔗[ docs.obol.org/add-validators](https://docs.obol.org/advanced-and-troubleshooting/advanced/add-validators) + +**Background**: This feature would allow users to dynamically add validators post-launch via DappNode. It is not currently supported and would require someone familiar with the Obol DappNode integration layer. + +**Expected Deliverables:** + +* Integrate add-validator logic into DappNode package +* Ensure compatibility with Charon +* Include light documentation and testing instructions + +**Budget**: \~$1,000 USD + +**Funding**: Milestone-based, paid in $OBOL equivalent + +## 🟠 In Progress {#in-progress} +### TEEs for DVT Security (Sebastian Faust, PolyCrypt GmbH) {#tees-for-dvt-security-sebastian-faust-polycrypt-gmbh} +**Goal**: Prototype and benchmark how Trusted Execution Environments (Intel TDX) can secure DV operations. + +**Expected Deliverables:** + +* Run a DVT node (Charon + VC) inside Intel TDX +* Benchmark performance and risk mitigation +* Produce documentation, open-source code, and in-depth report + +**Funding**: $10,000 in stables + $10,000 in $OBOL + +**Status**: Started (September 2025) + +### Ansible Playbooks for Obol DVT (Jeremiah Sullivan) {#ansible-playbooks-for-obol-dvt-jeremiah-sullivan} +**Goal**: Build automated Ansible roles for DVT cluster deployment and home staking setups. + +**Scope**: + +* Docker Images with CI/CD for DVT components +* Ansible Roles for Charon deployment and validator configuration +* Monitoring setup with Grafana dashboards and webhook alerts +* Step-by-step documentation + +**Funding**: 7,000 $OBOL + +**Milestones**: Final delivery expected Q4 2025 + +**Status**: Ongoing (public GitHub in progress) diff --git a/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-staking-masters.md b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-staking-masters.md new file mode 100644 index 0000000000..19e62e9652 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/grants-program/grants-track-for-staking-masters.md @@ -0,0 +1,81 @@ +--- +sidebar_label: "Grants Track for Staking Masters" +slug: /community-and-governance/community/grants-program/grants-track-for-staking-masters +--- + +# Grants Track for Staking Masters + +This track covers proposals aligned with the [Collective’s SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388). + +It is designed for Staking Masters who want to proactively work on strategic initiatives that support Obol’s mission. + +You can browse funded grants and milestone details for this track on[ ](https://questbook.app/grants/obol/track-name-placeholder)[Questbook](https://questbook.app/dashboard/?grantId=68d792a86fd5365ca2538329\&chainId=10). + +*** + +## Overview, Eligibility and Scope {#overview-eligibility-and-scope} +The **Staking Mastery Program** is a rolling grant track designed to empower individual contributors and small technical teams working to advance distributed staking. This track revives the ethos of the original [Staking Mastery Cohorts](../staking-masters.md) by preserving their spirit of excellence, but adapts the structure to support proactive applications aligned with the [Obol Collective’s 2025 SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388). + +Unlike the original cohort-based model, this new iteration operates on a rolling basis. Contributors can apply at any time to work on initiatives that push forward distributed validator adoption, improve technical general infrastructure, or deliver impactful research. The focus here is technical. One time education initiatives are supported separately through our [Community Events track](grants-track-for-community-events.md). + +This grant track is designed for proactive applications submitted by individual contributors or small teams interested in helping the Collective move forward. These can include topics such as: + +* Deepening DV penetration in staking and restaking protocols +* Expanding DV accessibility through tooling or automation +* Improving infrastructure compatibility with Obol DVs +* Conducting meaningful research in distributed validator technologies +* Integrating Defi protocols or adding more utility to the token + +**To be eligible, applications must:** + +* Be aligned with the 2025 SQUAD Goals of the Obol Collective +* Propose realistic deliverables that advance distributed staking +* Be led by individuals or small teams with proven technical expertise in staking, governance, infrastructure, or Ethereum protocols + +There is no fixed format or size constraint for proposals. We welcome both small- and large-scope projects but they should be concrete, measurable, and narratively clear. + +## Budget & Funding {#budget-and-funding} +Applicants must request funding using the template included in the application form. All budgets should be **denominated in $OBOL**, and payments will be made in **OBOL tokens**. + +Grants are **milestone-based**. This means: + +* Funding is **not disbursed upfront**. +* Each milestone must be **completed and approved** before the associated funding is released. +* Once a milestone is validated, the grantee can move on to the next phase and receive subsequent funding. + +## Submission Process {#submission-process} +There is no deadline or wave. Applications are accepted on a **rolling basis**. + +To apply, simply [fill out the dedicated application form](https://forms.gle/hJfXtGZFZqNoWAyE8), which includes sections for: + +* An overview of your project and its alignment with the Collective’s SQUAD Goals +* A breakdown of proposed milestones and deliverables +* Team background and relevant experience +* A detailed cost breakdown and requested budget (USD-denominated for the cost breakdown and converted into $OBOL for the budget request) + +## Evaluation & Review {#evaluation-and-review} +Once a submission is received, applicants can expect an **initial triage within 7 business days**. This first response will fall into one of three categories: + +1. ✅ **Accepted** — you’re good to move forward as-is. +2. ❌ **Rejected** — the proposal is not aligned or not feasible at this time. +3. 💬 **Discussion Required** — we’re interested, but need further alignment on scope, milestones, or budget. + +In most cases, we anticipate some **back-and-forth discussion** to refine the proposal before final approval. + +Once aligned, applicants will be asked to **submit the final version** of the grant to Questbook, including: + +* Project overview +* Final milestones +* Approved budget + +Questbook will serve as the **source of truth** for the proposal and allow anyone to **track the funding on-chain.** + +## Expectations & Visibility {#expectations-and-visibility} +We want to showcase the valuable work being built across the ecosystem. + +Upon completion of significant milestones (or the full project), we’ll highlight the grant publicly via: + +* Obol’s social channels +* Periodic blog posts or newsletters summarizing recent grants + +We also encourage grantees to share their own updates publicly, to **build visibility** for both their work and the broader Collective. diff --git a/versioned_docs/version-v1.7/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.7/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..e88964cd95 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/staking-masters.md @@ -0,0 +1,27 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program (Archived)" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\\ + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.7/community-and-governance/community/techne.md b/versioned_docs/version-v1.7/community-and-governance/community/techne.md new file mode 100644 index 0000000000..f7897a2455 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/community/techne.md @@ -0,0 +1,120 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\\ + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::info +For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. +::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.obol.org) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.obol.org) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.obol.org) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.7/community-and-governance/contribution/README.md b/versioned_docs/version-v1.7/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..5cff17667a --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# contribution + diff --git a/versioned_docs/version-v1.7/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.7/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +```markdown + ```javascript + console.log(error); + ``` +``` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.7/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.7/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e17d6226af --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +- Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +- Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/README.md b/versioned_docs/version-v1.7/community-and-governance/governance/README.md new file mode 100644 index 0000000000..55b1235949 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/README.md @@ -0,0 +1,58 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# Governance + +The Obol Collective is building a decentralized governance system rooted in the core values of Web3: transparency, openness, collaboration, and community-led decision making. At the same time, we recognize that decentralization is a journey, not a switch. Our aim is to progressively decentralize Obol governance in a way that is sustainable, resilient, and free of the common pitfalls that have emerged in the ecosystem. + +## Our Vision: Pragmatic Decentralization + +We are here to stay. And we believe the only way to build a resilient and successful decentralized collective is to start by building a strong foundation. In recent months, many leading DAOs have experienced operational bottlenecks, inefficiency, and growing pains from decentralizing too fast, too early. The result? Several are now walking back toward more centralized structures to regain coordination capacity, accountability, and operational agility. + +We’ve learned from these examples. Our approach is different: we are deliberately not rushing into maximal decentralization. Instead, we are laying the groundwork for progressive, sustainable decentralization over time. + +At this stage of the Collective, execution matters. Proposals are already going through governance processes, but the Obol Association still holds executional authority to move quickly where needed. We see this as a temporary and necessary condition to keep building and shipping. This balance, transparent governance with accountable execution, is critical to avoid decision paralysis. + +Governance at Obol is not about decentralization for its own sake. It is about enabling the best decisions for the long-term health of the network. As emphasized in the [Bell Curve governance roundtable](https://youtu.be/vF8XuRuZs9g?si=0dw3uh8gLXyvFlUH), decentralization without shared purpose or coordination leads to deadlock. We aim to build a governance model that supports rather than hinders progress. + +## Inspiration + +We draw inspiration from both the successes and challenges of other DAOs. In particular: + +* [**Arbitrum DAO**](https://forum.arbitrum.foundation/t/a-vision-for-the-future-of-arbitrum/28962), Introduced “Arbitrum Aligned Entities” to fix governance gridlock by assigning execution to focused teams, while keeping strategic control with the DAO. A response to over-decentralizing too quickly and losing operational clarity. +* [**Compound**](https://www.comp.xyz/t/proposal-to-create-the-compound-foundation/6777?utm_source=substack\&utm_medium=email), Proposed the Compound Foundation to help the DAO coordinate services, manage treasury execution, and maintain continuity — moving from pure DAO toward a hybrid model with accountable support. + +These initiatives reinforce our belief that progressive decentralization, aligned with clear domain ownership and accountable entities, leads to more sustainable governance. + +## Principles We Follow + +* **Decentralization is a means, not an end.** Governance exists to serve the network, not to complicate it. +* **Stakeholders should govern what they understand.** Validators and technical contributors guide protocol upgrades; token holders lead incentive and treasury decisions. +* **Social consensus is paramount.** On-chain votes matter, but upgrades only succeed through real-world coordination and adoption. +* **Structures must evolve with the protocol.** Governance at genesis won’t look like governance at maturity. We are building toward that future in deliberate steps. + +## Governance Tools + +To support transparent decision-making and empower active participation, here are key tools used across the Collective: + +* [**Governance Forum**](https://community.obol.org/) – for proposal discussion and coordination +* [**Voting Portal**](https://vote.obol.org/) – to delegate or vote on proposals +* [**Dune Dashboard**](https://dune.com/vistalabs/obol-governance) – to track voting data and delegate participation +* [**Staking Portal**](https://stake.obol.org/) – to stake OBOL and receive stOBOL +* [**0xretro.xyz**](https://0xretro.xyz/) – to access key info and metrics about delegates +* [**Curia Labs Dashboard**](https://obol.curiahub.xyz/delegate) – to find detailed insights on delegate reputation scores and contributions + +## Governance Sections + +The Obol governance documentation is organized into the following sections: + +* [collective.md](collective.md "mention") – framing the governance bodies, roles, and progressive decentralization pathway +* [token-house.md](token-house.md "mention") – the token-holder-based decision-making layer of the Collective +* [raf](raf/README.md "mention") – information for delegates participating in the Retroactive Funding Program (RAF) +* [grants-program](../community/grants-program/README.md "mention") – the Obol funding mechanism for contributors and ecosystem support, led by the Obol Association + +_These sections evolve as the governance process matures. For any feedback, ideas, or questions, we invite you to join the discussion on the_ [_Forum_](https://community.obol.org/) _or reach out via_ [_Discord_](https://discord.obol.org)_._ + +**Together, we are building governance for the long term.** diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/collective.md b/versioned_docs/version-v1.7/community-and-governance/governance/collective.md new file mode 100644 index 0000000000..4b93a757a8 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/collective.md @@ -0,0 +1,62 @@ +--- +description: "Obol Collective Overview" +sidebar_label: "Collective Overview" +slug: /community-and-governance/governance/collective +--- + +# Collective Overview + +## Purpose + +The Obol Collective’s governance system has two primary goals: + +1. **Resource allocation.** Allocate resources effectively to support the Collective’s vision and grow the Obol Collective's sustainable value. Long-term vision may sometimes conflict with short-term value creation; thus, governance requires a blend of short-term and long-term thinking to allocate the token treasury and protocol revenue effectively. +2. **Capture resistance.** Governance plays a key role in securing the anti-capture and censorship resistance of the Obol Collective. Governance should: + 1. make it possible for operations to continue over the long term without reliance on any individual entity; + 2. prevent any one entity or small group of entities from being able to control or censor. + +## Overview: The Obol Token House and RAF + +Two houses govern the Obol Collective: the Token House and the Obol RAF. + +In the **Token House,** OBOL Token holders are responsible for submitting, deliberating, and voting on governance proposals using the Governance Portal. Token holders can delegate their OBOL Token voting power to their own address or an eligible third party. Addresses with delegated voting power are called “Delegates”. + +In the **Obol Retroactive Fund (RAF)**, OBOL Token Delegates are responsible for allocating funds within the RAF to projects and teams that provide value to the Obol Collective. + +All OBOL holders and Delegates are expected to exercise their authority responsibly and follow the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. + +![](/img/gitbook/image-51.png) + +## The Security Council + +The Security Council is a committee of multi-sig wallet signers with the power to perform certain emergency actions as delegated to it by the Obol Association. + +The Security Council can execute any software upgrade or perform other emergency actions without delay to respond to a security emergency, should one arise. The Security Council must not use its power to perform Emergency Actions except in a true security emergency, such as a critical vulnerability that could significantly compromise the Obol Collective. + +After taking any Emergency Action, the Security Council must issue a full transparency report (at an appropriate time after the security emergency has passed) explaining what was done and why such action was justified. + +## Administration and Implementation + +In all cases, Obol Collective governance is intended to be carried out in a manner consistent with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. The Obol Association will steward this process as described below, with the goal of increasingly decentralising its role over time. + +The Obol Association, via its governance administrators, will facilitate administration to ensure that anyone may participate thoughtfully in governance. Such administrative services may include: + +* Moderation of governance proposals to ensure they are validly submitted and voted upon; +* Removal of proposals that reasonably appear to be fraudulent, spam-oriented, defamatory, hateful, or otherwise inappropriate or inconsistent with the values of the Collective; +* Monitoring of votes, voting power, the votable token supply, and voting periods for purposes of determining whether quorums and approval thresholds are met or accurately reflected; +* Management of mutually contradictory or duplicate proposals that are submitted simultaneously or close to one another; +* Maintenance of the Governance & RAF Portal; +* Other tasks that the Obol Association deems appropriate in connection with the above. + +The Association may also intervene operationally when necessary to uphold the integrity of the governance process — for instance, by removing improperly submitted proposals or enforcing community-agreed rules. When doing so, it will always act transparently and share justifications with the community. + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal or chosen RAF recipients, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails, coupled with an explanation. + +## Vision for Fully On-Chain Governance + +Once Collective’s governance develops and is deemed as sufficiently mature by the Obol Association, the implementations of passed proposals will follow full on-chain execution, where possible. Instead of the Collective’s reliance on the Obol Association for implementation, passed proposals will be moved to a queue to prepare for execution. The queue action will send the proposal to a Timelock contract, which starts a countdown until the proposal can be executed. + +Executing a proposal will run its function calls on-chain. Each proposal can be associated with one or more function calls. These calls will perform actions such as transferring assets from the treasury, updating the Governor's parameters, or calling another smart contract. diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/delegate-guide.md b/versioned_docs/version-v1.7/community-and-governance/governance/delegate-guide.md new file mode 100644 index 0000000000..5071ec9d15 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/delegate-guide.md @@ -0,0 +1,33 @@ +--- +description: "Delegate Guide" +sidebar_label: "Delegate Guide" +slug: /community-and-governance/governance/delegate-guide +--- + +# Delegate Guide + +## Delegate Rules of Engagement + +This document outlines the expectations, responsibilities, and values that should guide interactions within the Obol Collective governance community, including the Obol Forum, Discord, and working group meetings. This Code of Conduct will be reviewed periodically to incorporate feedback and adapt to governance needs. Any changes require community approval through the governance process. + +Please review these principles carefully to ensure alignment with the Obol Collective’s vision and commitment to a decentralized and sustainable ecosystem. + +Please read the rules of engagement on the forum [here](https://community.obol.org/t/delegates-rules-of-engagement/206). + +## **Governance Toolkit** + +These tools or their uses may change over time as governance evolves. For example, additional user interfaces dedicated to governance may be developed. Likewise, while voting currently takes place on-chain through the Governance Contract, some successful votes are administered and implemented by the Obol Association, which should not be the case indefinitely. + +Please see the toolkit on the forum [here](https://community.obol.org/t/governance-toolkit/207). + +## Delegates’ Role in the RAF + +The role of Delegates in the RAF is to allocate votes to projects that have made substantial positive impact on the Obol Collective’s Decentralized Operator Ecosystem. Vote allocation is proportional to the Delegates’ delegated power. To determine the funding amounts, the [quadratic funding](https://qf.gitcoin.co/) mechanism is used, to ensure a balanced and equitable distribution of influence. + +Visit read [the delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) on the forum. + +## Delegate Compensation + +Starting August 2025, active delegates will be eligible for compensation based on their participation and contributions. This is determined using the **Delegate Reputation Score (DRS):** a scoring system that evaluates each delegate’s voting, rationale, and forum activity. Only delegates with a score of **65 or higher** will qualify for rewards. + +For full details on DRS and how compensation works, see the [Delegate Reputation Score & Compensation page.](delegate-guide/delegate-reputation-score-and-compensation.md) diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md b/versioned_docs/version-v1.7/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md new file mode 100644 index 0000000000..7874f36dc3 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md @@ -0,0 +1,101 @@ +--- +sidebar_label: "Delegate Reputation Score & Compensation" +slug: /community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation +--- + +# Delegate Reputation Score & Compensation + +## Delegate Reputation Score & Compensation + +As the Obol Collective moves toward more mature governance, we are introducing a new system to help improve delegate accountability and guide token holder decisions: the **Delegate Reputation Score (DRS)**. + +This mechanism is part of a broader initiative to evolve token governance beyond simple vote counts but toward systems that reward quality participation and reinforce long-term alignment. + +The Obol Collective is among the first DAOs to integrate this model, developed in collaboration with [Tally](https://www.tally.xyz/) and [Curia](https://obol.curiahub.xyz/delegate), helping to pioneer a new standard for **reputation-backed delegate governance**. + +## What is the Delegate Reputation Score (DRS)? {#what-is-the-delegate-reputation-score-drs} +The Delegate Reputation Score is a reputation system. It gives each delegate a score from 0 to 100 based on their behaviour across three core dimensions: + +* **Voting participation** +* **Forum rationale submissions** +* **Forum engagement (discussion and replies)** + +These inputs are tracked over a rolling window of proposals, with scoring updates happening after [every **governance cycle** (every 21 days)](https://app.gitbook.com/s/ym0xLVqLq5ZCK1Q02khi/community-and-governance/governance/token-house#token-house-governance-proposal-process). The current scoring logic can be found in full detail on [Curia’s documentation](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f), which also serves as the canonical source of truth. + +:::tip +**When does my DRS update?** + +Scores are updated every 21-day governance cycle, but with a 6-day delay after the submission window closes. + +This ensures all proposals, including those submitted just before the deadline, have completed their full voting period before scores are recalculated. This buffer guarantees consistency and fairness across the cycle. +::: + +Delegates can view their scores, and token holders can browse and filter delegates based on their reputation and activity levels directly on [Tally](https://www.tally.xyz/gov/obol/delegates). + +### Why it matters {#why-it-matters} +CommentThe DRS is designed to: + +* Help token holders delegate more effectively, with clearer visibility into how delegates are behaving +* Increase accountability by making governance activity measurable and comparable +* Reinforce quality and trust within the delegate set + +In practice, this means token holders are strongly encouraged, through the UI and incentive systems, to **delegate to high-DRS delegates**, while delegates are incentivized to maintain an active and transparent presence in the Collective’s governance. + +_**This is not just a dashboard feature. DRS has real consequences for rewards and visibility.**_ + +### Delegate Statuses by DRS + +Delegates can fall into different categories based on their Delegate Reputation Score (DRS), which is recalculated after every governance cycle. These statuses help token holders understand delegate behavior and make informed delegation decisions: + +* Active: Delegates with a DRS ≥ 65 are considered _active. T_his is the ideal status. Active delegates are eligible for compensation and prominently displayed in the UI to encourage token holders to delegate to them. + * Active (New): A delegate with a DRS ≥ 65 but who has participated in fewer than 5 proposals. While still considered active, this tag highlights that the delegate is relatively new, and their track record is limited. +* Inactive: Delegates with a DRS < 65. These delegates have either skipped votes or failed to post rationales, indicating lower governance engagement. + * Inactive (New): New delegates (fewer than 5 proposals) whose early participation has not met the DRS threshold. This tag signals limited history and insufficient engagement so far. +* Ghost: Delegates who have received voting power but have never participated in any governance vote. Once they vote on a proposal, they’ll transition into an active or inactive status depending on their initial DRS, and will also carry the “new delegate” tag until they surpass 5 evaluated proposals. + +### Bootstrapping New Delegates + +To avoid penalizing new contributors, DRS includes a bootstrapping mechanism. A delegate’s first vote will trigger their scoring process, and their initial DRS will be calculated based on that single proposal. Over time, the DRS evolves into a moving average across the last 5 proposals they were eligible to vote on. This ensures: + +* New delegates who actively participate from the start can achieve a high DRS immediately +* Inconsistent delegates see their score adjust quickly +* A consistent track record is required to maintain an active status + +Additionally, new delegates will be visibly tagged as such in the UI, signaling that their DRS is based on limited history. This helps token holders assess delegation options with full context and encourages early but consistent engagement. + +This design balances the need to reward early participation while preventing score manipulation. Active delegates (even if new) become eligible for compensation as soon as they meet the DRS threshold. + +## Delegate Compensation + +_Delegate Compensation is not live yet. It is scheduled to launch in the second part of August 2025._ + +We are also introducing **delegate compensations**, funded by the Delegate Rewards Pool. Compensation is **gated by DRS**: only delegates with a score of **65 or above** are considered “active” and eligible. + +Once classified as active, rewards are distributed using a **square root model**, based on delegated voting power. This model was selected to strike a balance between influence and fairness: + +* It reduces reward concentration among the largest delegates +* It supports smaller, high-performing delegates +* It helps foster a more pluralistic and sustainable governance ecosystem + +This approach is experimental and will be closely monitored. Over time, we may revisit weighting or distribution methods based on observed outcomes. + +### **Why Delegate Compensation?** + +At Obol, we believe that **no one should work for free. B**ut we also recognize that **not all participation is equally meaningful**. Delegate compensation isn’t about paying people to hold tokens or rubber-stamp votes. It’s about rewarding those who consistently engage with care, post structured rationales, and help the Collective navigate complex governance questions with thoughtfulness and integrity. + +Compensation is now earned through **visible, active contribution —** whether through dissent, alignment, or creative proposals — as long as it’s expressed in a way that moves the Collective forward. Good-faith disagreement and diversity of thought are part of what makes a governance system resilient. That’s the work we want to support. + +## A collaborative standard + +The DRS is a shared initiative between Obol, Tally (UI and standardization), and Curia (calculation and onchain oracle). While the Obol Collective is among the first to adopt this system, the hope is that it will be used by other DAOs seeking to upgrade their delegate models. + +We are proud to help drive this standard forward and will continue sharing learnings as we refine the system in practice. + +## Resources + +* [Tally Delegate Portal](https://www.tally.xyz/gov/obol/delegates) – see live DRS scores, search delegates, and explore participation history +* [Curia Dashboard](https://obol.curiahub.xyz/delegate) – DRS calculation details and complementary metrics +* [Curia's Source of truth for scoring logic](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f) – Broken down calculation of DRS +* [OIP-4: Delegate Compensation & DRS Scoring](https://community.obol.org/t/oip-4-delegate-compensation-and-delegate-reputation-score-integration-for-stobol/522) – original governance proposal + +\\ diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/raf/README.md b/versioned_docs/version-v1.7/community-and-governance/governance/raf/README.md new file mode 100644 index 0000000000..44acaa1f05 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/raf/README.md @@ -0,0 +1,76 @@ +--- +description: "The RAF" +sidebar_label: "The RAF" +slug: /community-and-governance/governance/raf +--- + +# The RAF + +Obol’s Retroactive Funding (RAF) mechanism is designed to strengthen and promote the decentralisation of Ethereum's settlement layer by rewarding projects that add value and drive impact for Ethereum’s decentralisation. Read more about the Obol RAF [here](https://blog.obol.org/1-percent-for-decentralisation/). + +Voting and funding distributions occur over a series of **Obol Retroactive Fund (RAF)** rounds, with OBOL token Delegates determining how funds from the RAF are allocated. The first RAF round will open in February 2025. + +## Overview of the Obol RAF: + +* Any project that meets the RAF round’s criteria can make an application. +* OBOL Token Delegates vote on applications proportional to their delegated power and using [quadratic funding](https://qf.gitcoin.co/). +* The Obol RAF rounds occur at intervals and include phases for scoping, application creation, application review, voting, and funding distribution. +* The Obol Association will collect information from projects to distribute grants, including KYC, where required. + +Below is described the steps within each RAF round. Each step takes approximately one week.\\ + +![](/img/gitbook/image-53.png) + +### Step 1: Scoping + +The scope of the round’s impact and the amount of funding to be allocated is defined by the Obol Association at the outset of the round and posted on the Obol Forum. + +### Step 2: Application Registration + +Projects are invited to create an application on the [RAF App](http://raf.obol.org/). Any project or team can apply, but in the future, governance may decide that an application needs to be made by someone holding a minimum amount of OBOL tokens. + +Once a RAF round is opened, to apply for the Obol RAF, projects can create an application on [raf.obol.org](http://raf.obol.org/) by following these steps: + +1. **Create an Application:** Fill out the application form using the [RAF App](http://raf.obol.org/). +2. **Describe Impact:** Specify the category of the project and its impact. + +### Step 3: Application Review + +A subset of OBOL Delegates appointed by the Obol Association reviews applications to ensure compliance with the application rules. + +The Obol Association will also review applications to filter out spam or applications that do not align with the mission of the Obol Collective. + +### Step 4: Voting + +OBOL Delegates vote on projects in proportion to their voting power. Here’s how it works: + +1. **Eligibility:** Every address that has been delegated voting power by OBOL Token holders can submit votes. +2. **Voting Process:** Delegates vote using the [raf.obol.org](http://raf.obol.org) app. Depending on the type of application being reviewed, a specific set of criteria should be used to judge a project's contributions to the Obol Collective. + +:::warning +The Obol Association will monitor votes to ensure contributors are not voting for projects they are directly involved in or where a substantial conflict of interest may be present. Delegates are expected to act in accordance with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. +::: + +### Step 5: Tallying Results + +The voting power of each OBOL Token Delegate is proportional to the amount of OBOL tokens delegated to them. However, the funding results are calculated using [quadratic funding](https://qf.gitcoin.co/), meaning that the square root of the votes is used to determine the final allocation. This approach ensures a broader distribution of funding across the Obol Collective, rather than allowing a small number of winners to dominate. + +### Step 6: Compliance + +The Obol Association will review the list of selected projects, adjust if necessary and collect information from them to distribute the grant legally compliantly (including completing KYC if required). + +### Step 7: Funding distribution + +The overall reward amount for the round is divided among the winning projects based on the delegates' vote and allocation according to the quadratic funding mechanism. + +### **Step 8: Community retrospective** + +After each round, The Obol Association will conduct a retrospective and gather community feedback. + +## Guides for each Round + +RAF1: see the [RAF1 guide](https://community.obol.org/t/guide-for-raf-round-1-raf1/227) in the forum. + +## RAF1 Summary & Insights + +Head over to [raf1-guide.md](raf1-guide.md "mention") to find the results, top projects, and key takeaways from our first round. diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/raf/raf1-guide.md b/versioned_docs/version-v1.7/community-and-governance/governance/raf/raf1-guide.md new file mode 100644 index 0000000000..0acc913186 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/raf/raf1-guide.md @@ -0,0 +1,27 @@ +--- +sidebar_label: "RAF #1" +slug: /community-and-governance/governance/raf/raf1-guide +--- + +# RAF #1 + +## Learnings from RAF Round 1 + +Our first Retroactive Funding round (RAF1) awarded 1 million OBOL to 46 projects using a quadratic voting mechanism. Projects were evaluated on technical impact, contribution to decentralization, and public goods alignment. + +### Top-funded projects included: + +* Dappnode — integrated Obol into their Dappstore, enabling 16k+ validators to use Obol setups. +* Ethereum on ARM — ran distributed validators on low-cost devices. +* Stereum — offered one-click node deployment with Obol pre-installed, backed by strong GitHub and beaconcha.in adoption metrics. + +### Key learnings: + +* Impact evaluation is challenging without clear data; future rounds may require stronger entry thresholds. +* Quadratic voting worked to elevate broadly supported projects, but needed clearer onboarding. +* Delegates requested better UX for wallets and real-time visibility into vote progress. +* Community engagement was strong but limited in feedback volume — improving outreach will be a focus + +_**We’re using these insights to shape future RAF rounds, with an emphasis on transparency, fairness, and long-term ecosystem impact.**_ + +👉 [Read the full blog post here](https://blog.obol.org/raf1-results/) diff --git a/versioned_docs/version-v1.7/community-and-governance/governance/token-house.md b/versioned_docs/version-v1.7/community-and-governance/governance/token-house.md new file mode 100644 index 0000000000..25a60f8ed3 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/governance/token-house.md @@ -0,0 +1,121 @@ +--- +description: "The Token House" +sidebar_label: "The Token House" +slug: /community-and-governance/governance/token-house +--- + +# The Token House + +In the Token House, OBOL Token holders are responsible for submitting, deliberating, and voting on various Obol Collective governance proposals. + +## Overview of the Obol Token House + +* Proposals are reviewed and voted on in three-week cycles. + +:::info +You can subscribe to the public calendar [here](https://calendar.google.com/calendar/u/0?cid=Y183YzQ0ZmYwZjM5ODE4ZTcyODg2OTM2MmI4ZWEyMGNmMDdhMmZmMmZiMzMxYjE2MjMwYzg3ZjQxZGRiYjA4N2ViQGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20\&ref=blog.obol.org) so you always know where the current cycle stands. +::: + +* In the first week, anyone may draft a proposal of any type based on [this template](https://community.obol.org/t/proposal-template/208) and post it on the [Forum](https://community.obol.org/) with \[Draft] in the title. Delegates, Obol Collective members, and the general public can provide feedback on proposals in the forum, which should be incorporated into the proposal using the author’s best judgment. +* Once your proposal has been approved by four top-100 Delegates (by voting power), add a link to your proposal to the Voting Cycle Roundup forum thread by the last day of Week 2, and update the title from \[Draft] to \[Final]. The proposal then moves on to Week 3: Voting. +* If your proposal is passed, the Obol Association will facilitate its administration, including distributing approved OBOL Tokens grants. +* If your proposal fails, you can make a new proposal in the next cycle, specifying how you have incorporated significant changes from your first proposal.\\ + + ![](/img/gitbook/Token_house.png) + +## Token House Governance Proposal Process + +Anyone can submit a proposal to the Token House by using the Governance Portal. Proposals are accepted or rejected using a voting process. A proposal must be one of the valid proposal types listed below and follow the voting process described here. + +All governance proposals go through a 3-week cycle. Each “week” runs from Thursday at 7:00 pm GMT until Wednesday at 7:00 pm GMT. + +### Valid Proposal Types + +All governance proposals must fall within one of the following categories: + +* Ecosystem grants +* Protocol upgrades +* Token inflation adjustment +* Treasury allocations +* Work agreements +* Veto on the Obol RAF operations + +The different requirements for submission and approval of each Proposal Type are summarized below. If a specific template is not specified below, proposals should follow this standard proposal template. + +All Ecosystem grant applications are processed by the Association. + +Below are listed types of Token House Proposals. Each has a two-week review period plus one week voting window, with an approval threshold of 51%. + +| Proposal Type | Description | Submission Requirements | +| :-----------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------- | +| Ecosystem grants | The Obol Association’s treasury may be used to support development of the Collective and/or growth of the ecosystem via the proposal template. | Forum proposal + On-Chain Voting | +| Token inflation adjustment | Changes to the OBOL Token Contract or its supply. | Forum proposal + On-Chain Voting | +| Treasury Appropriations | The amount of OBOL Tokens the Obol Association may spend or distribute annually | Proposal initiated by the Association + On-Chain Voting | +| Work agreements | Formal arrangements between the Obol Association and contributors, teams, or organizations tasked with advancing specific initiatives or responsibilities within the ecosystem | Forum proposal + On-Chain Voting | +| Veto on the Obol RAF operations | The veto mechanism serves as a safeguard against decisions or actions within the RAF operations that are misaligned with the mission of decentralization, transparency, or the collective interests of the community. | Forum proposal + On-Chain Voting | +| Protocol upgrades | Scheduled changes to the on-chain smart contracts comprising the protocol or governance contracts. | Forum proposal + On-Chain Voting | +| SQUAD Goals | It reflects the aim of establishing shared, strategic, and community-driven objectives. Goals are set annually, with each cycle beginning in April. | Forum proposal + On-Chain Voting | + +### Weeks 1-2: Feedback and Review + +All proposal types should be posted to the [Obol Forum](https://community.obol.org/) for review. Proposal authors are expected to respond to feedback from Obol Collective members and Delegates. + +Proposals should be: + +* Submitted as a new discussion thread on the [Governance Forum](http://community.obol.tech/) in the appropriate Proposal Category. +* Marked with \[Draft] in the title. +* Formatted and contain information consistent with the [standard proposal template](https://community.obol.org/t/proposal-template/208). + +Before the end of Week 2, a governance administrator will create a Voting Cycle Roundup thread in the forum summarising all the proposals that meet the voting requirements for Week 3 Voting. + +For proposals to proceed to Week 3, four of the top 100 delegates by voting power must give explicit approval on the discussion thread. Delegates may signal approval by pasting the following comment on the proposal discussion thread: _”I am an Obol Delegate \[link to your delegate commitment in your Tally profile] with sufficient voting power, and I believe this proposal is ready to move to a vote."_ + +If a Delegate approves a proposal to move to a vote, it does not endorse that proposal. It simply signifies that they believe the proposal is ready to move to a vote. + +After receiving the required approvals, the author should update the proposal title from \[Draft] to \[Final] and add a link to their proposal in the Voting Cycle Roundup thread by the last day of Week 2 at 19:00 GMT. Authors should also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal’s progress. Proposal authors should include relevant links if feedback was gathered outside the Forum (e.g., on Discord). + +If a proposal author does not get explicit approval or wants more time for feedback, they should not include their proposal in the Voting Cycle Roundup thread. Instead, they should continue to seek community feedback and submit an updated proposal in the next voting cycle. + +:::warning +If a proposal that did not receive explicit approval through the steps above is submitted to the voting portal, the Obol Association reserves the right to cancel it onchain. While the Association is currently working to formalize this cancel authority within the Governor contract, this measure helps preserve governance integrity and ensures that only properly vetted proposals are voted on. +::: + +### Week 3: Publish a Proposal Onchain and Voting + +During Week 3, a wallet holding at least [30,000 OBOL in voting power](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c#readContract) must publish the proposal on the [Obol Governance Platform](https://www.tally.xyz/gov/obol).\ +After publication, there is a 24-hour voting delay, during which the proposal can be canceled if necessary. The voting delay is the amount of time between when a proposal is submitted and when it goes up for voting. The delay gives token holders time to delegate their voting power before the vote starts or buy more votes. Governor takes a snapshot of all the voting power at the start of voting. Read more [here](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/how-to-pick-governor-parameters#how-to-pick-the-voting-delay). + +:::warning +Important: Any proposal published on Tally must exactly match the version approved by top delegates on the forum—word for word. Adding new elements that were not explicitly approved is strictly forbidden. Additionally, proposal authors must keep the first post of the forum thread updated to reflect the latest version, so readers don’t have to search the comment section for changes. +::: + +\ +After the 24 hours, Delegates (including OBOL Token holders who have self-delegated) vote on proposals via the [Obol Governance Portal](https://vote.obol.org/). All proposals are included in voting if they were added to the Voting Cycle Roundup thread before the deadline and have the approval of four top-100 delegates. + +A governance proposal is **approved** if it satisfies two requirements: + +* **Quorum:** A minimum number of OBOL Token votes measured as _a % of the total votable OBOL Token supply, as of the start of the voting period._ “Votable supply” is the total amount of OBOL Tokens that have been delegated (including to oneself) and, therefore, can participate in voting. The current definition for the OBOL Token House is 0.84% of minted supply. +* **Approval threshold:** The minimum _% of votes cast in support relative to the total number of votes._ The current definition for the OBOL Token House is 0.01% of minted supply. + +A snapshot is taken at the start of each voting period to determine each delegate’s voting power. Voting is hosted on the Obol Governance Portal. + +If a proposal is submitted for a vote and does not pass, the proposal will not be executed. If a proposal author wishes to iterate on a rejected proposal, they should: + +1. Create a new proposal thread on the Forum. +2. Include a link to the first proposal that did not pass. +3. Clearly identify what has changed in the new proposal. + +:::warning +If the same proposal fails to pass two consecutive times (i.e., it is rejected onchain twice in a row), it may not be reintroduced or submitted again for a minimum period of 5 **governance cycles** — roughly equivalent to 3.5 **months** (based on the current 3-week cycle length). This ensures that only well-formed, broadly supported proposals proceed and discourages repeated cycling of the same topic without meaningful revision or support. +::: + +### Timelock Delay + +After the voting period ends, if the proposal passes, there will be a 5-day timelock delay. The timelock delay is the minimum time required between the approval and execution of a proposal. This delay gives stakeholders a final opportunity to review and react before the proposal is implemented. Read more [here](token-house.md#implementation). + +## Implementation + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails. diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/README.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/README.md new file mode 100644 index 0000000000..4daa098a9c --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/README.md @@ -0,0 +1,105 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/obol-token +--- + +# The OBOL Token + +The OBOL Token is central to the governance and operation of the Obol Collective. It serves multiple purposes that are essential to its functioning. + +**OBOL Token Transferability:** With the approval of[ OIP-2](https://community.obol.org/t/oip-2-unlock-obol-token/317/30), the OBOL Token is set for a strategic and well-planned unlock. The tokens will be unlocked on the 7th May 2025 at 11:00 UTC, following the completion of centralized exchange listings. Please go to [claim.obol.org](https://claim.obol.org) to unlock airdrop tokens. + +## Token Contract + +The official token contract address of the OBOL Token is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7) + +## Official Uniswap Pool + +The official Uniswap Pool for the OBOL Token is [https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434](https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434) + +## Verified Contract Addresses {#verified-contract-addresses} +The following smart contracts power OBOL staking, governance, and reward distribution on Ethereum mainnet. + +
+ +Governor Contract + +* **Address:** [`0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c`](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c) + +- **Purpose:** Manages onchain proposal lifecycle and voting logic for Token House governance. +- **What you can find onchain:** + * Voting thresholds + * Quorum settings, + * Delay/period configs, + * Proposal and vote history. + +
+ +
+ +Obol Staker + +* **Address:** [`0x30641013934ec7625c9e73a4D63aab4201004259`](https://etherscan.io/address/0x30641013934ec7625c9e73a4D63aab4201004259) + +- **Purpose:** This is the base layer of the Obol staking system. It facilitates the basic mechanics of staking, such as managing deposits, forwarding governance delegation, and streaming rewards based on earning power. +- **What you can find onchain:** + * Total OBOL staked in the contract + * Stake, earning power, rewards and balances on a granular, per-deposit basis + * Current reward rate and configuration + * Contract events (e.g. `Staked`, `Withdrawn`) + * Interactions for staking/unstaking + +
+ +
+ +stOBOL (ERC-20 Token Contract) + +* **Address:** [`0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC`](https://etherscan.io/address/0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC) +* **Purpose:** A liquid ERC-20 representation of staked OBOL built on top of the Obol Staker. It adds features like transferability, reward auto compounding, and the ability to use a staked OBOL position in other protocols. Holders retain the ability to delegate their staked tokens to the governance delagate of their choice. +* **What you can find onchain:** + * ERC-20 metadata (name, symbol, decimals) + * Total supply and balances + * Transfer history + * Allowances / approvals + * Voting power interface (via `getVotes` and `delegates`) + * Event logs for delegation changes + +
+ +
+ +Reward Notifier + +* **Address:** [`0x384dd81047F88eE35DE75DA1149943B8e62d8802`](https://etherscan.io/address/0x384dd81047F88eE35DE75DA1149943B8e62d8802) +* **Purpose:** Manages the distribution of tokens to the staking contract so they can be streamed as rewards to stakers. +* **What you can find onchain:** + * Current and past reward rate values + * Administrative role settings (who can push updates) + * Timing/config changes made through proposals + * Events like `RewardRateUpdated` + +
+ +
+ +Auto Delegate (Overwhelming Support Strategy) + +* **Address:** [`0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158`](https://etherscan.io/address/0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158) +* **Purpose:** Implements the “Overwhelming Support” auto-delegation strategy. This contract casts votes on behalf of un-delegated or transferred stOBOL when proposals receive strong community support. This mechanism uses tokens that would otherwise not be available in governance to ensure uncontroversial proposals will meet quorum. +* **What you can find onchain:** + * Parameters like `supportThreshold`, `subQuorumBips`, and `votingWindow` + * Proposals voted on by the strategy + * Vote power amounts cast + * Event logs showing execution activity + * Wallets or protocols interacting with auto-delegation logic + +
+ +## Learn more about... + +[token-utility.md](token-utility.md) +[staking-and-stobol.md](staking-and-stobol.md) +[token-distribution-and-liquidity.md](token-distribution-and-liquidity.md) +[token-holders-faq.md](token-holders-faq.md) +[tge-faq.md](tge-faq.md) diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/staking-and-stobol.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/staking-and-stobol.md new file mode 100644 index 0000000000..f2c58623fa --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/staking-and-stobol.md @@ -0,0 +1,78 @@ +--- +description: "This page explains how OBOL staking works, the role of stOBOL, and what happens when tokens are delegated, transferred, or used in DeFi protocols. You can stake and unstake OBOL via stake.obol.org." +sidebar_label: "Staking & stOBOL" +slug: /community-and-governance/obol-token/staking-and-stobol +--- + +# Staking & stOBOL + +## Overview + +Staking allows OBOL token holders to participate in governance while earning rewards. When you stake OBOL, you receive a liquid staking token called stOBOL. This token is transferable, composable in DeFi, and earns staking rewards while maintaining governance power, as long as it remains in the same address that originally staked the OBOL Tokens. It represents a flexible and powerful tool to both support the network and engage in the broader ecosystem. + +stOBOL unlocks new opportunities for participation. It is yield-bearing, enables seamless governance engagement, and is expected to be increasingly integrated across DeFi platforms. If it is transferred elsewhere, direct delegation is removed and governance power is reassigned an Auto-Delegate, preventing governance attacks. The voting behaviour of the Auto-Delegate is determined by the active strategy. + +### To Recap + +* stOBOL is a liquid staking token received when you stake OBOL. +* It allows users to earn staking rewards which auto-compound while retaining governance power. +* stOBOL is fully transferable (ERC-20) and can be used in DeFi (e.g., as collateral). + +## Key Concepts + +
FeatureOBOLstOBOL
Governance voting✅ (direct or delegated)✅ (only if kept on original staking address, otherwise governance power reallocated to the Auto-Delegate)
Transferable
Used in DeFi✅ (less efficient, not yield-bearing)✅ (yield-bearing)
Earns staking rewards
+ +## Delegation & Governance + +Governance power is fundamentally tied to the OBOL Token. When OBOL is staked, the governance power does not transfer to stOBOL itself but remains associated with the underlying staked OBOL. stOBOL serves as a representation of that staked position, surfacing its governance power **only while being held in the same address** that originally staked the OBOL. + +If stOBOL is transferred to another address or smart contract, governance power is not automatically preserved. Instead: + +* By default, the governance power is reassigned to the **Auto-Delegate**. +* However, the receiving address or smart contract **can explicitly delegate** the voting power of its stOBOL to a delegate of choice, if such functionality is supported. + +This design ensures that governance power follows clear, transparent rules: + +* **No double-counting**: the OBOL held in the staking contract is not counted separately from the stOBOL in circulation. +* **No governance arbitrage**: someone cannot gain voting rights simply by borrowing or acquiring stOBOL without also controlling the original staking delegation. + +If stOBOL is used in DeFi protocols (e.g., as collateral on Morpho), governance power defaults to the Auto-Delegate unless the protocol itself implements explicit delegation support for pooled stOBOL assets. + +## How the Auto-Delegate Strategy Works (Current: Overwhelming Support) + +When a liquid staking token (like stOBOL) is transferred, any previous delegation is removed. To prevent this from harming quorum or enabling governance attacks, the system can route that voting power through the Auto-Delegate strategy. The first strategy implemented is called the "Overwhelming Support". This fallback strategy only casts votes using its accrued governance power **in favor** of a proposal when all the following conditions are met: + +* **Sub-quorum reached:** At least 66% of the quorum is already met by FOR votes (`subQuorumBips = 66%`). +* **High support threshold:** At least 90% of votes cast so far are FOR votes (`supportThreshold = 90%`). +* **Within final voting window:** The proposal is within \~2.5 days of its deadline (`votingWindow = 14400` blocks). + +If all three criteria are met, the strategy casts its voting power FOR the proposal. If not, it abstains. + +This ensures that fallback voting power (from transferred stOBOL) is only used to support proposals that already have overwhelming community backing. It avoids influencing contentious or split decisions, protecting governance neutrality and reducing capture risk. + +This model preserves network governance while allowing for stOBOL to flow through DeFi protocols. + +Other strategies can be proposed via governance. + +## Summary Flow + +1. OBOL is staked and stOBOL is minted to the staker’s address. +2. While stOBOL remains with the same address, governance power is retained and delegated as usual. +3. If stOBOL is transferred, governance power is removed and reassigned via the current Auto-Delegate strategy (Overwhelming Support). Other strategies can be proposed via governance. + +![](/img/gitbook/stOBOL_03-3-1.png) + +## Additional Notes + +* You can stake and unstake OBOL via [stake.obol.org](https://vote.obol.org/stake). +* Voting and delegation are managed at [vote.obol.org](https://vote.obol.org/). + +The Auto-Delegate and underlying strategies are modular and designed to evolve. It represents an initial approach to handling undelegated voting power, but additional strategies can be proposed by the Collective over time. As the Collective matures, we expect to iterate and improve on these mechanisms together. + +As the protocol evolves, new strategies or staking configurations may be introduced through Collective governance. Feedback from the community helps inform these decisions. + +Have questions? Join our [Discord](https://discord.gg/n6ebKsX46w) or visit the [Governance Forum](https://community.obol.org). + +*** + +_This page will evolve as more staking strategies and integrations are launched._ diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/tge-faq.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/tge-faq.md new file mode 100644 index 0000000000..2d2e3766a6 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/tge-faq.md @@ -0,0 +1,170 @@ +--- +sidebar_label: "TGE FAQ" +slug: /community-and-governance/obol-token/tge-faq +--- + +# TGE FAQ + +## Unlock and Listing + +
+ +How do I unlock my OBOL Tokens received in the Airdrop? + +Starting May 7th at 11:00 AM UTC, visit [**claim.obol.org**](https://claim.obol.org), click **“Unlock”**, and follow the steps. + +
+ +
+ +When is the official TGE date and time? + +The OBOL Token will be listed on exchanges for deposit, trading and withdrawals on May 7th, 2025 at 11:00 AM UTC + +
+ +
+ +Where will the OBOL Token be listed for trading? + +* **Binance**, **Bybit**, **Bitget**, **Gate.io**, **MEXC**, and others. + +- Check [CoinGecko](https://coingecko.com) or [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) for the most up-to-date list. + +
+ +
+ +What are the exact listing times on exchanges? + +* **Binance Alpha** – _May 7 at 10:00 AM UTC_ + +- **Binance Futures** – _May 7 at 10:30 AM UTC_ + +* **Bybit, Gate.io, Bitget, MEXC** – _May 7 at 11:00 AM UTC_ + +
+ +
+ +Where can I track the price of the OBOL Token? + +[CoinGecko](https://coingecko.com) and [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) + +
+ +
+ +Where can I buy the OBOL Token onchain? + +* A **Uniswap v3 pool** will be seeded with initial liquidity. + +- The contract address is [here](https://etherscan.io/address/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434). + +* Anyone can start a pool. Check live prices via **CoinGecko**, or **CoinMarketCap**. + +
+ +
+ +Are there any country restrictions for claiming or trading the OBOL Token? + +* Yes. Each venue has its own restrictions. + +- Unlocking OBOL Tokens received through the Airdrop is subject to the same geo restrictions as claiming. + +
+ +## **Token Supply & Distribution** + +
+ +What is the circulating supply at TGE? + +Approximately 19**%**. Full breakdown is on [CoinMarketCap](https://coinmarketcap.com/currencies/obol/). + +
+ +
+ +Why does Etherscan show 374M tokens instead of 500M? + +For legal and tax reasons, not all tokens are minted yet. + +
+ +
+ +How many tokens were allocated to CoinList, and how many unlock at TGE? + +Details available on the [**Coinlist Sale Page**](https://coinlist.co/obol). + +
+ +
+ +When were unclaimed airdrop tokens returned to the treasury? + +As approved by [**OIP-2**](https://community.obol.org/t/oip-2-unlock-obol-token/317), they were [returned](https://etherscan.io/tx/0x738b4c252bb4613b9945e3b6426ec4ee510c6cdb86027fe20d533c4799a3a331) on **May 2, 2025**. + +
+ +## **Unlocks & Vesting** + +
+ +Can CoinList participants claim at TGE? + +Yes, a portion of their tokens will unlock on May 7th at 11AM UTC per the [**Coinlist terms**](https://coinlist.co/obol). + +
+ +
+ +Will RAF1 tokens be available at TGE? + +RAF1 tokens will be distributed **shortly after TGE**. + +
+ +
+ +When will OBOL Token incentives be claimable? + +Starting May 12, 2025 + +
+ +## **Token Utility** + +
+ +What is the utility of the OBOL Token? + +See the top of the page + +
+ +
+ +What is stOBOL? + +A staked version of the OBOL Token that can be used in DeFi or with restaking platforms. + +
+ +
+ +Can the OBOL or stOBOL Tokens be used in DeFi? + +Yes. More info will follow **post-TGE**. + +
+ +
+ +Are there incentives for providing DeFi liquidity with OBOL or stOBOL? + +**Not at TGE**, but proposals for incentives can be submitted via governance. + +
diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/token-distribution-and-liquidity.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/token-distribution-and-liquidity.md new file mode 100644 index 0000000000..649045f286 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/token-distribution-and-liquidity.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Distribution & Liquidity" +slug: /community-and-governance/obol-token/token-distribution-and-liquidity +--- + +# Token Distribution & Liquidity + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](https://docs.obol.org/community-and-governance/governance/raf)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/token-holders-faq.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/token-holders-faq.md new file mode 100644 index 0000000000..4876719cca --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/token-holders-faq.md @@ -0,0 +1,135 @@ +--- +description: "This page is designed to answer the most common questions from OBOL token holders, particularly those holding liquid OBOL or stOBOL." +sidebar_label: "Token Holders FAQ" +slug: /community-and-governance/obol-token/token-holders-faq +--- + +# Token Holders FAQ + +## General + +
+ +What is the OBOL token used for? + +OBOL is the governance token of the Obol Collective. It enables holders to participate in on-chain governance by voting directly or delegating their voting power to delegates. + +OBOL is also used in the [RAF](../governance/raf/), where token holders delegate to vote on which contributors should receive retroactive funding for valuable work. + +In addition, OBOL can be staked to receive stOBOL, a liquid token that accrues staking rewards and retains governance power as long as it remains in the staker’s wallet. This staking mechanism supports long-term alignment and decentralized ownership. + +Finally, both OBOL and stOBOL are being integrated into DeFi protocols, such as liquidity pools, lending platforms (e.g. Morpho), and restaking services (e.g. Eigenlayer, Symbiotic), with more utility expected over time as shaped by community governance. + +
+ +
+ +What is stOBOL? + +stOBOL is the liquid staking token received when you stake OBOL. It earns staking rewards and can be used in DeFi. Holding stOBOL in your wallet preserves your governance power. More info in [staking-and-stobol.md](staking-and-stobol.md "mention") + +
+ +
+ +Where can I see OBOL price, supply, and markets? + +You can track OBOL on [CoinMarketCap](https://www.coingecko.com/en/coins/obol-2) or [Coingecko](https://coingecko.com). These pages include market data, supply information, and live price charts. + +
+ +## Delegation & Governance + +
+ +How do I delegate my OBOL tokens? + +You can delegate via [vote.obol.org](https://vote.obol.org/dao/delegates). Connect your wallet, choose a delegate, and confirm the delegation transaction. + +
+ +
+ +What happens if I stake OBOL? + +You receive stOBOL, which maintains your delegation as long as it stays in your wallet. Once transferred (e.g., to a DeFi protocol), you lose the individual delegation. Voting power is then routed via an [auto-delegation strategy](staking-and-stobol.md#how-the-auto-delegate-strategy-works-current-overwhelming-support). + +
+ +
+ +Can I change my delegate? + +Yes, you can re-delegate at any time through the Collective Portal at [vote.obol.org](https://vote.obol.org) + +
+ +
+ +Does holding OBOL give me passive income? + +Not directly. Only staking OBOL (to receive auto-compounding stOBOL) allows you to earn rewards. + +
+ +## Staking & stOBOL + +
+ +How do I stake OBOL? + +Use [stake.obol.org](https://stake.obol.org) to stake. You’ll receive auto-compounding stOBOL in return. + +
+ +
+ +Can I transfer stOBOL? + +Yes, stOBOL is a fully transferable ERC-20 token. However, if you transfer it, your direct delegation is lost, and your governance power enters the auto-delegation pool. + +
+ +
+ +Where can I use stOBOL? + +stOBOL can be used in DeFi protocols (e.g., as collateral, in LPs, etc.). Integrations are ongoing and will be announced via Discord and Twitter. Integrations are also documented [here](token-utility.md). + +
+ +
+ +Can I unstake OBOL? + +Yes. You can return stOBOL to the staking contract at anytime without lockup to reclaim your OBOL. Unstaking and restaking interfaces are provided at [stake.obol.org](https://stake.obol.org). + +
+ +## Token Value & Utility + +
+ +What gives the OBOL token value? + +OBOL gains utility through governance rights, staking yield, and its use in DeFi. Long term, its value could be tied to the growth of the Obol Network, including fees, protocol usage, and TVL. + +
+ +
+ +Does OBOL accrue fees? + +Currently, OBOL does not accrue protocol revenue. However, the DAO may vote in the future to direct protocol revenue toward token holders or stakers. + +
+ +
+ +How can I stay up to date on OBOL news? + +Join our [Discord](https://discord.obol.org), follow [@ObolNetwork](https://x.com/Obol_Collective), and check our [Forum](https://community.obol.org) for governance and integration updates. + +
+ +_This page is updated regularly. If your question isn’t listed, reach out via Discord or the Governance Forum._ diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/token-utility.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/token-utility.md new file mode 100644 index 0000000000..4a4e0f112c --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/token-utility.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Utility" +slug: /community-and-governance/obol-token/token-utility +--- + +# Token Utility + +## **Governance** + +OBOL Token holders delegate their voting power to delegates who participate in the Token House decision-making processes. This includes voting on proposals affecting the Obol Collective’s direction, upgrades, and funding allocations. Read more about the Token House [here](../governance/token-house.md). + +## **Obol Retroactive Funding (RAF)** + +Token holders delegate their voting power to Delegates, who vote on the projects eligible for retroactive funding. Read more about the Obol RAF [here](../governance/raf/). + +## **OBOL Token Staking** + +As per[ OIP-1](https://community.obol.org/t/oip-1-building-and-enabling-staking-for-the-obol-token/312), OBOL token holders will have the opportunity to stake their tokens, contributing to the security and stability of the Collective by preserving governance while earning rewards and being able to engage in DeFi. Staking involves depositing OBOL tokens in a vault (without lockup) that automatically delegates the Tokens if not done already. In return, stakers receive stOBOL, which automatically accrues OBOL Tokens as rewards as it's price vs OBOL increases. + +This staking program will be implemented in phases, allowing the community to gradually engage in and benefit from the system while reinforcing the decentralization of the Obol Collective. For the first six months, the total rewards will be 0.33% of the total supply, providing early participants with attractive rewards. After this period, the staking rewards may be adjusted based on governance proposals and market conditions. This structured rollout ensures a sustainable and rewarding staking experience while reinforcing the decentralization of the Obol Collective. + +To get started, simply visit [https://stake.obol.org](https://stake.obol.org) and follow the staking flow — no technical setup required. The interface will guide you through selecting your wallet, choosing the amount to stake, and submitting the transaction. + +**You will find more info about the OBOL token staking in the dedicated** [staking-and-stobol.md](staking-and-stobol.md "mention") **section.** + +## **DeFi** + +Plans are in place to launch several DeFi avenues for the OBOL Token post-TGE, such as liquidity pools, lending protocols (e.g. Morpho) and restaking (e.g. Eigenlayer, Symbiotic). + +### Pendle Integration for stOBOL + +wstOBOL is supported on [Pendle Finance](https://app.pendle.finance/trade/pools/0x78954a6a2c2a08455f92e47c4e587feb7467bf37/zap/in?chain=ethereum), enabling users to access advanced yield strategies with their staked OBOL. wstOBOL is the wrapped version of stOBOL. + +For more info on wstOBOL, refer to our [dedicated page](wstobol.md). + +Through Pendle, users can isolate and trade the future yield of wstOBOL by buying or selling its **Principal Tokens (PT)** and **Yield Tokens (YT)**. + +This opens up new opportunities: holders can lock in fixed yield by purchasing PTs, speculate on rising yield by acquiring YTs, or passively earn through **liquidity provision**, which offers exposure to swap fees and additional PENDLE incentives. Importantly, Pendle pools are **permissionless**, and while the Obol Association has provided initial liquidity to bootstrap the market, anyone can contribute. For more details, refer to the [Pendle Academy](https://pendle.gitbook.io/pendle-academy) and [wstOBOL pool on Pendle](https://app.pendle.finance/trade). + +## **More Utility Coming Soon** + +Via Token House governance proposals in the [Governance Forum](https://community.obol.org/), the Obol community can add more functionality and utility to the OBOL Token. diff --git a/versioned_docs/version-v1.7/community-and-governance/obol-token/wstobol.md b/versioned_docs/version-v1.7/community-and-governance/obol-token/wstobol.md new file mode 100644 index 0000000000..cb6a5ccef2 --- /dev/null +++ b/versioned_docs/version-v1.7/community-and-governance/obol-token/wstobol.md @@ -0,0 +1,51 @@ +--- +sidebar_label: "wstOBOL" +slug: /community-and-governance/obol-token/wstobol +--- + +# wstOBOL + +### What is wstOBOL? {#what-is-wstobol} +When you stake OBOL, you receive stOBOL, a non-rebasing, auto-compounding token. + +* Your stOBOL balance stays constant in your wallet. +* The value of each stOBOL relative to OBOL increases over time as staking rewards accrue. + +Unlike “plain” LSTs like stETH, stOBOL is designed to preserve governance: each staked token maintains its delegation, ensuring governance always reflects the real economic stake. + +**wstOBOL (wrapped stOBOL)** is simply a wrapped version of stOBOL. It **carries the same yield and economics**, with rewards accruing via the same exchange-rate mechanism. The difference lies in integration: + +* stOBOL can introduce a minor 1-wei transfer variance due to its governance-preserving accounting. +* wstOBOL eliminates this by providing a perfectly static balance, making it fully compatible with DeFi protocols that require strict 1:1 transfers. + +Think of wstOBOL as the “DeFi-strict” form of stOBOL. It does not change how rewards work, only how the token behaves when integrated into external systems. + +#### Why does wstOBOL exist? {#why-does-wstobol-exist} +Some DeFi protocols cannot easily integrate stOBOL’s governance logic. wstOBOL simplifies adoption. stOBOL continues to safeguard governance rights, while wstOBOL ensures smooth DeFi use. + +**Not all integrations require wstOBOL.** Some can use stOBOL directly. We will keep this page updated so users know which path to take for each integration. For example, Pendle requires wstOBOL. + +### How does wrapping work? {#how-does-wrapping-work} +* **Wrapping**: you deposit stOBOL and receive the same amount of wstOBOL. +* **Unwrapping**: you return wstOBOL and receive the same amount of stOBOL. + +The number of tokens is 1:1. The economic value grows over time because **stOBOL’s exchange rate to OBOL increases**, and wstOBOL simply represents the same claim on that growing value. + +### User Flows {#user-flows} +You can manage wrapping and unwrapping directly on our [staking platform](https://vote.obol.org/dao/token/wrap). The process is fully integrated and intuitive: just head to the staking portal and you’ll see the following options: + +* **Stake (OBOL → stOBOL)**: Stake OBOL and receive stOBOL, which auto-compounds and preserves delegation. +* **Unstake (stOBOL → OBOL)**: Exit staking and redeem more OBOL back from stOBOL. +* **Wrap (stOBOL → wstOBOL)**: Convert stOBOL into wstOBOL for use in integrations that require strict accounting. +* **Unwrap (wstOBOL → stOBOL)**: Redeem wstOBOL back into stOBOL 1:1. + +### Where can I use wstOBOL? {#where-can-i-use-wstobol} +* [**Pendle Finance**](https://app.pendle.finance/trade/pools/0x78954a6a2c2a08455f92e47c4e587feb7467bf37/zap/in?chain=ethereum) (yield trading, fixed/floating yield markets). +* Future integrations in lending, borrowing, and liquidity protocols. + +### Risks & Considerations {#risks-and-considerations} +* Wrapping/unwrapping requires **gas fees**. +* UX involves an extra step for users who hold stOBOL and want to access these DeFi apps. + +### Learn More {#learn-more} +* [Pendle Documentation](https://pendle.gitbook.io/) diff --git a/versioned_docs/version-v1.7/learn/charon/README.md b/versioned_docs/version-v1.7/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.7/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.7/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.7/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..3612f45445 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/charon/charon-cli-reference.md @@ -0,0 +1,831 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.7.0`](https://github.com/ObolNetwork/charon/releases/tag/v1.7.0). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. + --zipped Create a tar archive compressed with gzip of the cluster directory after creation. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost (default "default") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH+ staked for each). (default 1) + --operator-addresses strings Comma-separated list of each operator's Ethereum address. + --operator-enrs strings Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + --publish Creates an invitation to the DKG ceremony on the DV Launchpad. Terms and conditions apply. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 30s) + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 1m0s) + --zipped Create a tar archive compressed with gzip of the target directory after creation. +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --consensus-protocol string Preferred consensus protocol name for the node. Selected automatically when not specified. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + --graffiti strings Comma-separated list or single graffiti string to include in block proposals. List maps to validator's public key in cluster lock. Appends "OB" suffix to graffiti. Maximum 28 bytes per graffiti. + --graffiti-disable-client-append Disables appending "OB" suffix to graffiti. Increases maximum bytes per graffiti to 32. + -h, --help Help for run + --jaeger-address string [DISABLED] Listening address for jaeger tracing. + --jaeger-service string [DISABLED] Service name used for jaeger tracing. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --otlp-address string Listening address for OTLP gRPC tracing backend. + --otlp-headers strings Comma separated list of headers formatted as header=value, to include in OTLP requests. + --otlp-insecure Use insecure connection (no TLS) when connecting to OTLP endpoint. + --otlp-service-name string Service name used for OTLP gRPC tracing. (default "charon") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") + --vc-tls-cert-file string The path to the TLS certificate file used by charon for the validator client API endpoint. + --vc-tls-key-file string The path to the TLS private key file associated with the provided TLS certificate. +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its validator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + delete Delete a signed exit message from the remote API + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Delete exit message + +Delete a previously signed exit message for a given validator from the remote API. The required flag is either `--validator-public-key` of the validator message you wish to delete or `--all` to delete all validators' exit message. + +```markdown +charon exit delete --help +Deletes a partially signed exit message for a given validator from the remote API. + +Usage: + charon exit delete [flags] + +Flags: + --all Exit all currently active validators in the cluster. + -h, --help Help for delete + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default "./") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Generate and add new validators to a cluster + +The `charon alpha add-validators` command allows you to generate new validators and add them to an existing cluster. This process is very similar to the `charon dkg` ceremony, which requires all node operators to participate, because under the hood it runs the same DKG protocol with additional actions and verifications. + +:::warning +It is not yet recommended to use this command for Mainnet clusters. +::: + +```markdown +charon alpha add-validators --help +Generates and appends new validator keys to an existing distributed validator cluster. + +Usage: + charon alpha add-validators [flags] + +Flags: + --data-dir string The source charon folder with existing cluster data (lock, validator_keys, etc.). (default ".charon") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for add-validators + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --num-validators int The number of new validators to generate and add to the existing cluster. (default 1) + --output-dir string The destination folder for the new (combined) cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the command, should be increased if the command times out. (default 1m0s) + --unverified If charon has no access to the existing validator keys, this flag allows the addition to proceed, but skips hashing and signing the new cluster lock data. charon run must be started with --no-verify flag. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Test subcommands provide test suite to evaluate current cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure PingLoad DirectConn Libp2pTCPPortOpen PingRelay PingMeasureRelay Version Synced PingLoad Simulate1 Simulate100 Simulate500 Simulate1000 PingMeasure PeerCount Simulate10 SimulateCustom Ping Ping PingMeasure PingLoad Ping PingMeasure CreateBlock DiskWriteSpeed DiskReadSpeed DiskReadIOPS TotalMemory InternetLatency InternetDownloadSpeed InternetUploadSpeed DiskWriteIOPS AvailableMemory] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Simulate1000 SimulateCustom Version PingLoad Simulate10 Simulate500 Ping PingMeasure Synced PeerCount Simulate1 Simulate100] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [InternetDownloadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadSpeed AvailableMemory TotalMemory InternetLatency InternetUploadSpeed DiskReadIOPS] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [PingMeasure CreateBlock Ping] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://2.relay.obol.dev,https://1.relay.obol.tech]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [PingMeasure PingLoad DirectConn Ping Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.7/learn/charon/charon-networking.md b/versioned_docs/version-v1.7/learn/charon/charon-networking.md new file mode 100644 index 0000000000..3bed5e055d --- /dev/null +++ b/versioned_docs/version-v1.7/learn/charon/charon-networking.md @@ -0,0 +1,82 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview[​](https://docs.obol.org/learn/charon/networking#overview) {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](https://docs.obol.org/learn/charon/networking#internal-validator-stack) and the [_external p2p network_](https://docs.obol.org/learn/charon/networking#external-p2p-network). + +### Internal Validator Stack[​](https://docs.obol.org/learn/charon/networking#internal-validator-stack) {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network[​](https://docs.obol.org/learn/charon/networking#external-p2p-network) {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](https://docs.obol.org/learn/charon/charon-cli-reference): + +* `--p2p-tcp-addresses`: Addresses for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security[​](https://docs.obol.org/learn/charon/networking#libp2p-authentication-and-security) {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](https://docs.obol.org/learn/charon/cluster-configuration#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p’s Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery[​](https://docs.obol.org/learn/charon/networking#libp2p-relays-and-peer-discovery) {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives. Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\\ + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters[​](https://docs.obol.org/learn/charon/networking#scalable-relay-clusters) {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URLs. diff --git a/versioned_docs/version-v1.7/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.7/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..35b677f482 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralised backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long-term decentralisation of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability to remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore a trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.7/learn/charon/dkg.md b/versioned_docs/version-v1.7/learn/charon/dkg.md new file mode 100644 index 0000000000..5f7acf9daa --- /dev/null +++ b/versioned_docs/version-v1.7/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENR's nonce and resign with the client's private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participant's old keys out of a distributed validator in favour of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.7/learn/charon/intro.md b/versioned_docs/version-v1.7/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.7/learn/further-reading/README.md b/versioned_docs/version-v1.7/learn/further-reading/README.md new file mode 100644 index 0000000000..6432497dd7 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/further-reading/README.md @@ -0,0 +1,6 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading diff --git a/versioned_docs/version-v1.7/learn/further-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.7/learn/further-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..45e6731817 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/further-reading/ethereum_and_dvt.md @@ -0,0 +1,55 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum_and_dvt +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +\&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.7/learn/further-reading/peer_score.md b/versioned_docs/version-v1.7/learn/further-reading/peer_score.md new file mode 100644 index 0000000000..e79156eb98 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/further-reading/peer_score.md @@ -0,0 +1,48 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer_score +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of a rated network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.7/learn/further-reading/resources.md b/versioned_docs/version-v1.7/learn/further-reading/resources.md new file mode 100644 index 0000000000..dbd5286202 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/further-reading/resources.md @@ -0,0 +1,59 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/further-reading/resources +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.7/learn/further-reading/testnet.md b/versioned_docs/version-v1.7/learn/further-reading/testnet.md new file mode 100644 index 0000000000..9e69963aa5 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/further-reading/testnet.md @@ -0,0 +1,190 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/further-reading/testnet +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.7/learn/intro/README.md b/versioned_docs/version-v1.7/learn/intro/README.md new file mode 100644 index 0000000000..86437ddd26 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/README.md @@ -0,0 +1,9 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "README" +slug: /learn/intro/intro +unlisted: true +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.7/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.7/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..d495a8050d --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/readme/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General[​](https://docs.obol.org/learn/intro/faq#general) {#general} +#### Does Obol have a token?[​](https://docs.obol.org/learn/intro/faq#does-obol-have-a-token) {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/obol-token/) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is 0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7. + +#### Where can I learn more about Distributed Validators?[​](https://docs.obol.org/learn/intro/faq#where-can-i-learn-more-about-distributed-validators) {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from?[​](https://docs.obol.org/learn/intro/faq#where-does-the-name-charon-come-from) {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node?[​](https://docs.obol.org/learn/intro/faq#what-are-the-hardware-requirements-for-running-a-charon-node) {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster?[​](https://docs.obol.org/learn/intro/faq#what-is-the-difference-between-a-node-a-validator-and-a-cluster) {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine?[​](https://docs.obol.org/learn/intro/faq#can-i-migrate-an-existing-charon-node-to-a-new-machine) {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation[​](https://docs.obol.org/learn/intro/faq#distributed-key-generation) {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator?[​](https://docs.obol.org/learn/intro/faq#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator) {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum number of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-threshold). + +### Obol Splits[​](https://docs.obol.org/learn/intro/faq#obol-splits) {#obol-splits} +#### What are Obol Splits?[​](https://docs.obol.org/learn/intro/faq#what-are-obol-splits) {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in the future a number of other LSPs. + +#### Are Obol Splits non-custodial?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-non-custodial) {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split?[​](https://docs.obol.org/learn/intro/faq#can-i-change-the-percentages-in-a-split) {#can-i-change-the-percentages-in-a-split} +Generally, Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work?[​](https://docs.obol.org/learn/intro/faq#how-do-obol-splits-work) {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](https://docs.obol.org/learn/intro/obol-splits). + +#### Are Obol Splits open source?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-open-source) {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited?[​](https://docs.obol.org/learn/intro/faq#are-obol-splits-audited) {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](https://docs.obol.org/adv/security/smart_contract_audit). + +#### Are the Obol Splits contracts verified on Etherscan?[​](https://docs.obol.org/learn/intro/faq#are-the-obol-splits-contracts-verified-on-etherscan) {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts?[​](https://docs.obol.org/learn/intro/faq#does-my-cold-wallet-have-to-call-the-obol-splits-contracts) {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits?[​](https://docs.obol.org/learn/intro/faq#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits) {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient), its audit [here](https://docs.obol.org/adv/security/smart_contract_audit), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs[​](https://docs.obol.org/learn/intro/faq#debugging-errors-in-logs) {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](https://docs.obol.org/adv/troubleshooting/errors). diff --git a/versioned_docs/version-v1.7/learn/intro/key-concepts.md b/versioned_docs/version-v1.7/learn/intro/key-concepts.md new file mode 100644 index 0000000000..15e8cfcc73 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/key-concepts.md @@ -0,0 +1,117 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/readme/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimising downtime in mission-critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specialises in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof-of-stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys which together operate as a threshold key for participating in proof-of-stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that need to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 3 | 2/3 | Minimum to tolerate one offline node | +| 4 | 3/4 | Minimum to tolerate one **malicious** node | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +:::warning +Running the same Charon node in two places is considered a malicious (or byzantine) act, you should **take extra care not to run duplicate instances of a particular Charon peer if it is running in a three node setup**, which only tolerates one offline node, not a malicious one. Read more [here](../charon/cluster-configuration#cluster-size-and-resilience). +::: + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.7/learn/intro/launchpad.md b/versioned_docs/version-v1.7/learn/intro/launchpad.md new file mode 100644 index 0000000000..38c76daea3 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/launchpad.md @@ -0,0 +1,51 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/readme/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~** Staking Launchpad**](https://launchpad.ethereum.org/), a public good open-source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high-trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI-friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +| ---------------- | -------------------------------------- | +| Mainnet | https://launchpad.obol.org | +| Gnosis Chain | https://gnosischain.launchpad.obol.org | +| Hoodi | https://hoodi.launchpad.obol.org | +| Holesky | https://holesky.launchpad.obol.org | +| Sepolia | https://sepolia.launchpad.obol.org | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +> \[!TIP] If you created a cluster locally, and didn't use the `--publish` command at the time, you can manually publish it by running this command from the folder with the `cluster-lock.json` in it. +> +> `curl -X POST -H "Content-Type: application/json" -d @cluster-lock.json https://api.obol.tech/v1/lock` + +## Use the Explorer + +Clicking "explore" on the top-right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.7/learn/intro/obol-collective.md b/versioned_docs/version-v1.7/learn/intro/obol-collective.md new file mode 100644 index 0000000000..56ca205974 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/readme/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +The Obol Collective is the largest Decentralised Operator Ecosystem. We provide the technology, opportunities, and community to scale decentralised infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also Byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../further-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](https://docs.obol.org/api), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol's [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx), Obol's Distributed Validator Pod. +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.7/learn/intro/obol-incentives.md b/versioned_docs/version-v1.7/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..c673eb4a77 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/obol-incentives.md @@ -0,0 +1,178 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/readme/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible shortly after the OBOL Token is unlocked (as per O[IP#2](https://community.obol.org/t/oip-2-unlock-obol-token/)) and starts trading. + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralisation](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at any time but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.obol.org](https://discord.obol.org). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | diff --git a/versioned_docs/version-v1.7/learn/intro/obol-splits.md b/versioned_docs/version-v1.7/learn/intro/obol-splits.md new file mode 100644 index 0000000000..77b800bd9c --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/obol-splits.md @@ -0,0 +1,120 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/readme/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators and their surrounding ecosystem of decentralised infrastructure. These contracts include: + +* Withdrawal Recipients: Contracts used for a validator's withdrawal address, enabling the differentiation of principal stake from reward ether. +* Reward Splitting contracts: Contracts to split ether (and tokens) across multiple entities. Developed by [Splits.org](https://splits.org/) + +Key Design Principles the Obol Smart Contract suite include are: + +* That they are secure. All [released](https://github.com/ObolNetwork/obol-splits/releases/) Obol Splits products are [audited by high quality security teams](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments). +* They are not upgradeable. +* They are self-sovereign. Any permissioned actions, such as withdrawal, exit, or operator rotation, are controlled by the user, not an unaccountable set of third parties with the ability to upgrade your contract's behaviour. +* They do not require a token to function. +* They are oracle-free. (Unless you intend to leverage a [swapper](https://docs.splits.org/core/swapper)). +* They divide the reward ether from principal ether such that staking providers can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal and reward_. +* That rewards can be withdrawn in an ongoing manner without exiting the validator. (Some conditions apply). + + +## Optimistic Withdrawal Recipient[​](https://docs.obol.org/learn/intro/obol-splits#optimistic-withdrawal-recipient) {#withdrawal-recipients} +![](/img/gitbook/image-15-1-1.png) + +Optimistic Withdrawal Recipients (OWRs) **are the predecessor to Obol Validator Managers**. The primary addition with Validator Managers is the role-based control over validator withdrawals, exits and consolidations. + +Optimistic Withdrawal Recipients allow for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use a splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + +## Split Contracts[​](https://docs.obol.org/learn/intro/obol-splits#split-contracts) {#split-contracts} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Validator Managers focus on the former, split contracts focus on the latter. They are best used in tandem. + +![Obol Validator Manager in Tandem with an Execution Layer Fee recipient splitter contract](/img/gitbook/ovm_splits_overview.png) + +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers[​](https://docs.obol.org/learn/intro/obol-splits#split-controllers) {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. We recommend using a [SAFE wallet](https://safe.global) to manage the Split. + +#### (Gnosis) SAFE wallet[​](https://docs.obol.org/learn/intro/obol-splits#gnosis-safe-wallet) {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administer an editable split. The most well-known deployment of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + +## Deployments + +### Obol Lido Split Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#ols-factory-deployment) + +The `ObolLidoSplit` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/lido/ObolLidoSplitFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | --------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | | +| Hoodi | [0xb633CD420aF83E8A5172e299104842b63dd97ab7](https://hoodi.etherscan.io/address/0xb633CD420aF83E8A5172e299104842b63dd97ab7) | +| Holesky | | +| Sepolia | | + +### OWR Factory Deployment [**​**](https://docs.obol.org/learn/intro/obol-splits#owr-factory-deployment) + +The `OptimisticWithdrawalRecipient` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Holesky | [0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df](https://holesky.etherscan.io/address/0x7fec4add6b5ee2b6c1cba232bc6db754794cb6df) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | +| Hoodi | [0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7](https://hoodi.etherscan.io/address/0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7) | + +## FAQ + +### What are Obol Splits? + +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido with Obol Lido Splits, and Native Staking with Obol Validator Managers. + +### Are Obol Splits non-custodial? + +Yes. Unless you were to decide to [deploy an editable splitter contract](obol-splits.md#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. Obol Validator Managers have owners and Role-Based Access Control, but these are self-sovereign and up to the deployer to set and manage. There is no third party with access to or control of your validators unless you grant them such access. + +### Can I change the percentages in a split? + +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +### Are Obol Splits open source? + +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +### Are Obol Splits audited? + +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments) and always deploy contracts only from published [releases](https://github.com/ObolNetwork/obol-splits/releases). + +### Are the Obol Splits contracts verified on Etherscan? + +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +### Does my cold wallet have to call the Obol Splits contracts? + +No. Any address can trigger the contracts to distribute the withdrawn/skimmed ether, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +### Are there any edge cases I should be aware of when using Obol Splits? + +The most important thing to be aware of is what address is the owner of the Obol Validator Manager, whether it has assigned any other addresses any roles, and whether or not the Split contract you are using has been set up with editability and by which address. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is to use a high threshold multi-sign like a SAFE as the `owner`/`controller`, or to renounce ownership and control entirely, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](obol-splits.md#withdrawal-recipients), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. diff --git a/versioned_docs/version-v1.7/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.7/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..becb3a6d90 --- /dev/null +++ b/versioned_docs/version-v1.7/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/readme/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and PKI + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.7/run-a-dv/integrations/README.md b/versioned_docs/version-v1.7/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..77e5bf9a25 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# integrations + diff --git a/versioned_docs/version-v1.7/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.7/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..b7b9b507a4 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,58 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) and other applications. + +### Pre-requisites[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#pre-requisites) {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](https://docs.obol.org/next/adv/advanced/quickstart-sdk) is required. + +### Create a SAFE to own the EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-safe-to-own-the-eigenpod) {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-an-eigenpod) {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-a-splitter-for-the-block-reward) {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#create-the-dv-cluster-invite) {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](https://docs.obol.org/next/run/start/quickstart_group) on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](https://docs.obol.org/next/run/integrations/quickstart-sdk) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator[​](https://docs.obol.org/next/run/integrations/quickstart-eigenpod#deposit-and-restake-your-distributed-validator) {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. + diff --git a/versioned_docs/version-v1.7/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.7/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..ff1a100819 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/integrations/dappnode.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# DappNode + +For setup, see quickstart guide:[​](https://docs.obol.org/next/run/integrations/Dappnode#for-setup-see-quickstart-guide) + +For set-up of a DV using DappNode, see the quickstart guide [Create a DV Alone](https://docs.obol.org/next/run/start/quickstart_alone), and select the appropriate tab for "DappNode". + +### Frequently asked questions[​](https://docs.obol.org/next/run/integrations/Dappnode#frequently-asked-questions) {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster?[​](https://docs.obol.org/next/run/integrations/Dappnode#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-the-validator-and-charon-volumes-to-use-the-same-enr-for-another-cluster) {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC?[​](https://docs.obol.org/next/run/integrations/Dappnode#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag-for-lodestar-vc) {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically.\\ + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol?[​](https://docs.obol.org/next/run/integrations/Dappnode#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-same-dappnode-machine-push-monitoring-data-from-both-clusters-to-obol) {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.7/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.7/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..005a1f798f --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,225 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://operatorportal.lido.fi/modules/community-staking-module) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from Holesky just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using the CSM widget and expanding `Specify Custom Addresses` to set the `Manager Address` to the cluster multi-sig (SAFE) and the `Rewards Address` to the Splits.org splitting contract. Finally, we'll be selecting `Extended` permissions type which grants `Manager Address` ultimate control over the Node Operator. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (this can be the same address used in the SAFE contract). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (recommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol protocol development, thereby earning [Obol Incentives](https://obol.org/incentives) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [protocoldevelopmentfee.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol protocol development. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated the CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create validator keys with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create. +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using your favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM V2 enables a new Operator Type called Identified Community Staker ("ICS"). The squad member who is an ICS should be the one to create the node through the CSM widget. Doing so ensures the clusters validators receive [ICS benefits](https://blog.lido.fi/unlock-exclusive-benefits-as-an-identified-community-staker/). + +ICS member heads to [csm.lido.fi](https://csm.lido.fi/) and connects their wallet. + +![](/img/gitbook/image-47.png) + +The ICS member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The ICS member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The ICS member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button. + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.7/run-a-dv/prepare/README.md b/versioned_docs/version-v1.7/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..6d77f77e82 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# prepare + diff --git a/versioned_docs/version-v1.7/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.7/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..da8f61b1da --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,99 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10mb/s internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25mb/s internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimise both performance and cost-effectiveness, it is recommended to prioritise physical over virtualised setups. Such configurations typically offer greater performance and minimise overhead associated with virtualisation, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimise Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimize potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes would potentially impact the fault tolerance of the cluster and as a result should be avoided. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. Be sure to use encrypted communication between your VC and the Charon client, potentially through a cloud-provided network, a self-managed network tunnel, a VPN, a Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), or other manner. + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration/#cluster-size-and-resilience)). + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](./test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +The clusters should consist of a combination of your preferred consensus, execution, and validator clients. It is recommended to include a combination of multiple clients in order to have a healthy client diversity within the cluster, ideally, if any single client type fails, it should be less than the fault tolerance of the cluster, and the validators should stay online/not do anything slashable. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Metrics Monitoring + +As requested by Obol Labs, node operators can push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. Our recommendation for operators is to independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (usually < 24 hours). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.7/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.7/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..1c94049a40 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatibility information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.7/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.7/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..34798e30b2 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,554 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + + +:::tip + +Adding the `--publish` flag to the below commands, and running the command from the directory containing your `.charon` folder, will submit the test results to the [Obol API](../../api/what-is-this-api.md). Publishing your performance reports grows the staking node dataset, and allows Obol and Ethereum development teams to make data-driven choices regarding the required specs for validating Ethereum. We hope you will consider opting in. + +::: + + + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + + +:::info + +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the `beacon` node and `validator` client tests, you need to point them toward the correct Docker container, this includes specifying the Docker container’s network. Check your docker networks with the command `docker network ls`. When you run the test command, specify the Docker network with `--network `. + +Read more about docker networking [here](https://docs.docker.com/engine/network/). + +::: + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](https://docs.obol.org/next/learn/charon/charon-cli-reference#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-holesky-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.7.0 alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.7.0 alpha test mev \ + --endpoints="https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + + + + +#### Pre-requisites + +The executable storage tests require `fio` to be installed on your host machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +#### Example run + +```sh +charon alpha test infra +``` + + + + + +#### Example run + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.7.0 alpha test infra \ + --disk-io-test-file-dir=/opt/charon/test +``` + + + diff --git a/versioned_docs/version-v1.7/run-a-dv/running/README.md b/versioned_docs/version-v1.7/run-a-dv/running/README.md new file mode 100644 index 0000000000..515e6cbede --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# running + diff --git a/versioned_docs/version-v1.7/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.7/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..3c7cddf6d9 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +Use any of the following tools to deposit. Please use the third-party tools at your own risk and always double check the staking contract address. + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. diff --git a/versioned_docs/version-v1.7/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.7/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..8bf951f495 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/running/claim-rewards.md @@ -0,0 +1,65 @@ +--- +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +Introduction[​](https://docs.obol.org/next/run/running/claim-rewards#introduction) + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator’s withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +The method for claiming rewards depends on the Cluster's withdrawal configuration, whether it's an [**OWR**](https://docs.obol.org/next/learn/intro/obol-splits#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](https://docs.obol.org/next/learn/intro/obol-splits#exitable-withdrawal-recipient) . The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +\\ + +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://holesky.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](https://docs.obol.org/run/integrations/lido-csm). | + +### Claim Flow[​](https://docs.obol.org/next/run/running/claim-rewards#claim-flow) {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](https://docs.obol.org/next/learn/intro/obol-splits). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +1. All validator rewards are accumulated in the validator's withdrawal address, which is a split wallet. +2. Claims can be triggered in two ways: + 1. **From addresses in the Splitter**: Splitter addresses will see a `Claim All` button. When the first address (e.g., address A) executes `Claim All`, it triggers a multi-call transaction to distribute rewards from all the split wallets associated with a cluster into the Split Main. The Split Main then sends address A’s proportion of the rewards (based on the split configuration at the time of cluster creation). All of this is executed with a single click for the first address. + 2. **From addresses not in the Splitter**: Non-splitter addresses will see a `Distribute All` button instead of `Claim All`. These addresses cannot claim rewards directly but can distribute rewards to the Split Main (subsidizing transaction fees for others). Operators can then claim rewards later by visiting the same cluster details page. +3. Internally, after clicking `Claim All` or `Distribute All`, the split wallet sends the funds to the Split Main contract. +4. The Split Main then sends proportional rewards to **address A**, completing steps 2a, 3, and 4 with a single click. +5. Other addresses (e.g., B, C, D) can later click on `Claim All` to receive their share of the rewards. + +### Launchpad Edge Cases[​](https://docs.obol.org/next/run/running/claim-rewards#launchpad-edge-cases) {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: The `Claimable` column doesn’t match the amount next to the `Claim All` button. {#case-1-the-claimable-column-doesnt-match-the-amount-next-to-the-claim-all-button} +![](/img/gitbook/image-87.png) + +![](/img/gitbook/image-1-1-1-1-1.png) + +In this scenario, someone else (a splitter or non-splitter address) has already distributed rewards to the Split Main (e.g., 0.12 ETH). However, your validators (4 in this case) have earned an additional 0.2 ETH in rewards. Your total effective claimable balance is 0.032 ETH, which you can claim using the `Claim All` button. + +:::info +Your total effective claimable amount will always be displayed next to the `Claim All` button. +::: + +#### Case 2: You don’t see a `Claim All` button but instead see `Distribute All`.[​](https://docs.obol.org/next/run/running/claim-rewards#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all) {#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all} +![](/img/gitbook/image-88.png) + +This happens because the connected address is not listed in the split configuration. You may have used a different operator address from the one in the splitter configuration. You can: + +* Distribute all rewards using the connected address for all operators and claim using your address in the splitter configuration. +* Switch to the splitter address and claim directly. + +Note: It costs the same gas to distribute rewards for one address as it does for all addresses. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows a `Claim All` amount. {#case-3-you-just-created-a-new-cluster-with-no-active-validators-or-rewards-but-it-shows-a-claim-all} +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all `Claim All` buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.7/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.7/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..5401b89f8f --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,933 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction[​](https://docs.obol.org/next/run/running/quickstart-exit#introduction) {#introduction} +Users looking to exit staking entirely and withdraw their full balance back must sign and broadcast a "voluntary exit" message with validator keys which will start the process of exiting from staking. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proportion of principal and rewards. + +There are two ways to sign the partial exit and broadcast the full exit. Both the solutions don't require gas. + +1. **Using the Charon’s exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via launchpad and ability to download partial exits and broadcast them later as required. Users don’t have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use launchpad to monitor exit status and will have to use grafana to query the partial exit status. + +:::info +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +As per your preferences, choose the correct combination of - + +1. **Network** : Mainnet or Holesky +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quanity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +#### Step 1: Submit partial exit {#introduction} + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message.\\ + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=holesky \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=holesky \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network holesky \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](https://docs.obol.org/img/PartialExitsStatus.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch[​](https://docs.obol.org/next/run/running/quickstart-exit#exit-epoch-and-withdrawable-epoch) {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.7/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.7/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..125a356201 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/running/monitoring.md @@ -0,0 +1,89 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/charonoverview/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show following page. Choose Discord in the `Integration` drop down.\\ + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md). + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.7/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.7/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..36495800df --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,124 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +#### Pull latest changes to the repo[​](https://docs.obol.org/next/run/running/update#pull-latest-changes-to-the-repo) {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack[​](https://docs.obol.org/next/run/running/update#create-or-recreate-your-dv-stack) {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +#### Conflicts[​](https://docs.obol.org/next/run/running/update#conflicts) {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + diff --git a/versioned_docs/version-v1.7/run-a-dv/start/README.md b/versioned_docs/version-v1.7/run-a-dv/start/README.md new file mode 100644 index 0000000000..f8e137e70b --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# start + diff --git a/versioned_docs/version-v1.7/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.7/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..d67a243046 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,201 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](https://docs.obol.org/learn/intro/key-concepts#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](https://docs.obol.org/run/start/quickstart_group) instead for this latter case. +::: + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_alone#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.7.0 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 create cluster \ + --nodes=6 \ + --network=holesky \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead \ + --publish +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](https://docs.obol.org/next/run/start/quickstart_alone#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately.\ +\ +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Holesky testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Set up the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](https://docs.obol.org/next/learn/charon/charon-cli-reference) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample.holesky .env +``` +::: + + diff --git a/versioned_docs/version-v1.7/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.7/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..126d337b32 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,604 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites[​](https://docs.obol.org/next/run/start/quickstart_group#pre-requisites) {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](https://docs.obol.org/next/run/prepare/deployment-best-practices#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](https://docs.obol.org/next/adv/troubleshooting/errors#docker-permission-denied-error) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client**[**​**](https://docs.obol.org/next/run/start/quickstart_group#prepare-an-execution-and-consensus-client) + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package**[**​**](https://docs.obol.org/next/run/start/quickstart_group#install-the-obol-dappnode-package) + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge** + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful** + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +**Collect addresses, configure the cluster, share the invitation** + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](https://docs.obol.org/next/learn/intro/launchpad) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](https://docs.obol.org/docs/dvl/intro#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + 1. Select the desired amount of validators (32 ETH each) the cluster will run. (Note that the mainnet launchpad is restricted to one validator for now.) + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr) in the "What is your charon client's ENR?" field. + 3. Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. + 4. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions of participating as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +**Join the cluster prepared by the creator** + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address provided to the leader.\\ + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue.\\ + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](https://docs.obol.org/next/run/start/quickstart_group#step-1-generate-an-enr).\\ + + ![](/img/gitbook/image-83.png) +6. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +7. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](https://docs.obol.org/next/learn/charon/dkg) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) \\ + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. \\ + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.7.0 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run.\\ + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page.\\ + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +**Create a DV Node Backup** + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present.\\ + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long-term. + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose, further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Holesky testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +```sh +# To prepare the node for the Holesky test network +# Copy ".env.sample.holesky", renaming it ".env" +cp .env.sample.holesky .env + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env +``` + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```sh + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +``` + +:::danger +Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. +::: + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/charonoverview/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). + + + + +:::danger +Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. +::: + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Stop your docker compose + +```sh +docker compose down +``` + +2. Uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +3. Uncomment `EL=el-none` and `CL=cl-none` variables in the `.env` file and comment `EL=el-nethermind` and `CL=cl-lighthouse` variables: + +```sh +... +#EL=el-nethermind +... +EL=el-none +... +#CL=cl-lighthouse +... +CL=cl-none +... +``` + +4. Start your docker compose + +```sh +docker compose up -d +``` + + + + +To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-generate) + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Holesky network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=holesky --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-import-key) + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ holesky teku +``` + +**Sedge Run**[**​**](https://docs.obol.org/next/run/start/quickstart_group#sedge-run) + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. + + + +Use an Ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. + + + +Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. + + + +Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. + + + +:::tip +In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is `:3610`. Read more about Charon's networking [here](https://docs.obol.org/next/learn/charon/networking). +::: + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](https://docs.obol.org/next/run/running/activate-dv) to begin staking. diff --git a/versioned_docs/version-v1.7/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.7/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..b9523a9226 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,56 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics to Obol Monitoring" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics to Obol Monitoring + +:::info +This is **optional** and does not confer any special privileges within the Obol Network. +::: + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](http://docs.obol.org/run-a-dv/start/quickstart_overview), and have been provided with **Monitoring Credentials** used to push distributed validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve your Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +#### Update the monitoring token in the `.env` file + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +#### Save the `.env` file and restart Prometheus + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab.\\ + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it.\\ + + ![](/img/gitbook/image-86.png) + + diff --git a/versioned_docs/version-v1.7/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.7/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..371dc03d45 --- /dev/null +++ b/versioned_docs/version-v1.7/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to utilise Distributed Validators for solo or multi-operator staking. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](./create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](./create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.7/sdk/classes/Client.md b/versioned_docs/version-v1.7/sdk/classes/Client.md new file mode 100644 index 0000000000..a19a70f5e8 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/classes/Client.md @@ -0,0 +1,244 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +### Extends + +* `Base` + +### Constructors + +#### new Client() + +> **new Client**(`config`, `signer`?): [`Client`](Client.md) + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | -------- | --------------------- | +| `config` | `object` | Client configurations | +| `config.baseUrl`? | `string` | obol-api url | +| `config.chainId`? | `number` | Blockchain network ID | +| `signer`? | `Signer` | ethersJS Signer | + +**Returns** + +[`Client`](Client.md) + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client: [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +**Overrides** + +`Base.constructor` + +**Defined in** + +index.ts:66 + +### Methods + +#### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`<`string`> + +Accepts Obol terms and conditions to be able to create or update data. + +**Returns** + +`Promise`<`string`> + +terms and conditions acceptance success message. + +**Throws** + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions: [acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +**Defined in** + +index.ts:79 + +*** + +#### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys OWR and Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| --------------------- | ------------------------------------------------------------- | --------------------------------------- | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit: [createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:133 + +*** + +#### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Deploys Splitter Proxy. + +**Parameters** + +| Parameter | Type | Description | +| ------------------- | ----------------------------------------------------------- | -------------------------------------------------- | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +**Returns** + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit: [createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +**Remarks** + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +**Defined in** + +index.ts:254 + +*** + +#### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`<`string`> + +Creates a cluster definition which contains cluster configuration. + +**Parameters** + +| Parameter | Type | Description | +| ------------ | ----------------------------------------------------- | ----------------------- | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +**Returns** + +`Promise`<`string`> + +config\_hash. + +**Throws** + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition: [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +**Defined in** + +index.ts:350 + +*** + +#### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Approves joining a cluster with specific configuration. + +**Parameters** + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition. + +**Throws** + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition: [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +**Defined in** + +index.ts:415 + +*** + +#### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | ---------------------------------------------------------- | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +**Returns** + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition for config hash + +**Throws** + +On not found config hash. + +An example of how to use getClusterDefinition: [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +**Defined in** + +index.ts:469 + +*** + +#### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +**Parameters** + +| Parameter | Type | Description | +| ------------ | -------- | -------------------------------------------- | +| `configHash` | `string` | The configuration hash in cluster-definition | + +**Returns** + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +**Throws** + +On not found cluster definition or lock. + +An example of how to use getClusterLock: [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +**Defined in** + +index.ts:488 diff --git a/versioned_docs/version-v1.7/sdk/classes/README.md b/versioned_docs/version-v1.7/sdk/classes/README.md new file mode 100644 index 0000000000..d71a58615e --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# classes + diff --git a/versioned_docs/version-v1.7/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.7/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..7e4d9cb8ef --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,16 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------------------ | -------- | ------------- | ----------- | +| `0x00000000` | `1` | Mainnet | types.ts:6 | +| `0x00001020` | `5` | Goerli/Prater | types.ts:9 | +| `0x00000064` | `100` | Gnosis Chain | types.ts:12 | +| `0x01017000` | `17000` | Holesky | types.ts:15 | +| `0x10000910` | `560048` | Hoodi | types.ts:18 | diff --git a/versioned_docs/version-v1.7/sdk/enumerations/README.md b/versioned_docs/version-v1.7/sdk/enumerations/README.md new file mode 100644 index 0000000000..5069f1f6ed --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# enumerations + diff --git a/versioned_docs/version-v1.7/sdk/functions/README.md b/versioned_docs/version-v1.7/sdk/functions/README.md new file mode 100644 index 0000000000..62be7a3a85 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# functions + diff --git a/versioned_docs/version-v1.7/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.7/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..cb920b4b8b --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/functions/validateClusterLock.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock + +> **validateClusterLock**(`lock`): `Promise`<`boolean`> + +Verifies Cluster Lock's validity. + +### Parameters + +| Parameter | Type | Description | +| --------- | ----------------------------------------------- | ------------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | + +### Returns + +`Promise`<`boolean`> + +boolean result to indicate if lock is valid + +### Throws + +on missing keys or values. + +An example of how to use validateClusterLock: [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) + +### Defined in + +services.ts:13 diff --git a/versioned_docs/version-v1.7/sdk/index.md b/versioned_docs/version-v1.7/sdk/index.md new file mode 100644 index 0000000000..d22906b706 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/index.md @@ -0,0 +1,93 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + +# Intro + +**SDK Version:** v2.1.0 + +![Obol Logo](https://obol.org/obolnetwork.png) + +## Obol SDK + +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](https://docs.obol.org/api). + +### Getting Started + +Checkout our [docs](https://docs.obol.org/advanced/quickstart-sdk), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +### Terms and Conditions + +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +### ⚠️ Important Security Notice: + +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +* The private key is securely stored (e.g., in an `.env` file). +* Never commit or push your `.env` file containing the private key to version control. + +### Contributing + +Please review the following guidelines: + +* [How to Report Bugs](index.md#how-to-report-bugs) +* [How to Propose Changes](index.md#how-to-propose-changes) +* [Code Review Process](index.md#code-review-process) + +#### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +#### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +#### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +### Enumerations + +* [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +### Classes + +* [Client](classes/Client.md) + +### Interfaces + +* [ClusterDefinition](interfaces/ClusterDefinition.md) +* [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) + +### Type Aliases + +* [ClusterOperator](type-aliases/ClusterOperator.md) +* [OperatorPayload](type-aliases/OperatorPayload.md) +* [ClusterCreator](type-aliases/ClusterCreator.md) +* [ClusterValidator](type-aliases/ClusterValidator.md) +* [ClusterPayload](type-aliases/ClusterPayload.md) +* [SplitRecipient](type-aliases/SplitRecipient.md) +* [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +* [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +* [BuilderRegistration](type-aliases/BuilderRegistration.md) +* [DepositData](type-aliases/DepositData.md) +* [DistributedValidator](type-aliases/DistributedValidator.md) +* [ClusterLock](type-aliases/ClusterLock.md) +* [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) + +### Functions + +* [validateClusterLock](functions/validateClusterLock.md) diff --git a/versioned_docs/version-v1.7/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.7/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..b57096a0bf --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +Cluster definition data needed for dkg + +## Extends + +- [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | `ClusterPayload.name` | types.ts:73 | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)[] | The cluster nodes operators addresses. | `ClusterPayload.operators` | types.ts:76 | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)[] | The cluster validators information. | `ClusterPayload.validators` | types.ts:79 | +| `deposit_amounts?` | `null` \| `string`[] | The cluster partial deposits in gwei or 32000000000. | `ClusterPayload.deposit_amounts` | types.ts:82 | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | types.ts:90 | +| `version` | `string` | The cluster configuration version. | - | types.ts:93 | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | types.ts:96 | +| `fork_version` | `string` | The cluster fork version. | - | types.ts:99 | +| `uuid` | `string` | The cluster uuid. | - | types.ts:102 | +| `timestamp` | `string` | The cluster creation timestamp. | - | types.ts:105 | +| `config_hash` | `string` | The cluster configuration hash. | - | types.ts:108 | +| `threshold` | `number` | The distributed validator threshold. | - | types.ts:111 | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | types.ts:114 | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | types.ts:117 | diff --git a/versioned_docs/version-v1.7/sdk/interfaces/README.md b/versioned_docs/version-v1.7/sdk/interfaces/README.md new file mode 100644 index 0000000000..b635dbc6dc --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# interfaces + diff --git a/versioned_docs/version-v1.7/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.7/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..4ee32df936 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,24 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +# RewardsSplitPayload + +OWR and Split Proxy Params + +### Extends + +* [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +### Properties + +| Property | Type | Description | Inherited from | Defined in | +| -------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ------------ | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)\[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | types.ts:136 | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for Obol protocol development fee, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | types.ts:139 | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | types.ts:142 | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | types.ts:145 | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | types.ts:153 | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | types.ts:156 | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | types.ts:159 | diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.7/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..281cd48a13 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +> **BuilderRegistration**: `object` + +Pre-generated Signed Validator Builder Registration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | types.ts:184 | +| `signature` | `string` | BLS signature of the builder registration message. | types.ts:187 | + +## Defined in + +types.ts:182 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.7/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..f7467b4436 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +> **BuilderRegistrationMessage**: `object` + +Unsigned DV Builder Registration Message + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient` | `string` | The DV fee recipient. | types.ts:167 | +| `gas_limit` | `number` | Default is 30000000. | types.ts:170 | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | types.ts:173 | +| `pubkey` | `string` | The public key of the DV. | types.ts:176 | + +## Defined in + +types.ts:165 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..643f98978e --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +> **ClusterCreator**: `object` + +Cluster creator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The creator address. | types.ts:52 | +| `config_signature`? | `string` | The cluster configuration signature. | types.ts:54 | + +## Defined in + +types.ts:50 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..e386f0060e --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +> **ClusterLock**: `object` + +Cluster Details after DKG is complete + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | types.ts:235 | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)[] | The cluster distributed validators. | types.ts:238 | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | types.ts:241 | +| `lock_hash` | `string` | The hash of the cluster lock. | types.ts:244 | +| `node_signatures`? | `string`[] | Node Signature for the lock hash by the node secp256k1 key. | types.ts:247 | + +## Defined in + +types.ts:233 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..c12e7caa48 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +> **ClusterOperator**: `object` + +Node operator data + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The operator address. | types.ts:23 | +| `enr`? | `string` | The operator ethereum node record. | types.ts:26 | +| `fork_version`? | `string` | The cluster fork_version. | types.ts:29 | +| `version`? | `string` | The cluster version. | types.ts:32 | +| `enr_signature`? | `string` | The operator enr signature. | types.ts:35 | +| `config_signature`? | `string` | The operator configuration signature. | types.ts:38 | + +## Defined in + +types.ts:21 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..ab4d99aff2 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +> **ClusterPayload**: `object` + +Cluster configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | types.ts:73 | +| `operators` | [`ClusterOperator`](ClusterOperator.md)[] | The cluster nodes operators addresses. | types.ts:76 | +| `validators` | [`ClusterValidator`](ClusterValidator.md)[] | The cluster validators information. | types.ts:79 | +| `deposit_amounts`? | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | types.ts:82 | + +## Defined in + +types.ts:71 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..266d48a113 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +> **ClusterValidator**: `object` + +Validator withdrawal configuration + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | types.ts:62 | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | types.ts:65 | + +## Defined in + +types.ts:60 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.7/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..592d2f643b --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +> **DepositData**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | The public key of the distributed validator. | types.ts:195 | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | types.ts:198 | +| `amount` | `string` | 32 ethers. | types.ts:201 | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | types.ts:204 | +| `signature` | `string` | BLS signature of the deposit message. | types.ts:207 | + +## Defined in + +types.ts:193 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.7/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..5ec5dcc09d --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +> **DistributedValidator**: `object` + +Required deposit data for validator activation + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | types.ts:215 | +| `public_shares` | `string`[] | The public key of the node distributed validator share. | types.ts:218 | +| `deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\> | The deposit data for activating the DV. | types.ts:221 | +| `partial_deposit_data`? | `Partial`\<[`DepositData`](DepositData.md)\>[] | The deposit data with partial amounts or full amount for activating the DV. | types.ts:224 | +| `builder_registration`? | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | types.ts:227 | + +## Defined in + +types.ts:213 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.7/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..c08cb82c83 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +> **ETH\_ADDRESS**: `string` + +String expected to be Ethereum Address + +## Defined in + +types.ts:253 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.7/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..ee7810452c --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +> **OperatorPayload**: `Partial`\<[`ClusterOperator`](ClusterOperator.md)\> & `Required`\<`Pick`\<[`ClusterOperator`](ClusterOperator.md), `"enr"` \| `"version"`\>\> + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. + +## Defined in + +types.ts:44 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/README.md b/versioned_docs/version-v1.7/sdk/type-aliases/README.md new file mode 100644 index 0000000000..9e1ac60271 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# type-aliases + diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.7/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..e40db01a6c --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +> **SplitRecipient**: `object` + +Split Recipient Keys + +## Type declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `account` | `string` | The split recipient address. | types.ts:125 | +| `percentAllocation` | `number` | The recipient split. | types.ts:128 | + +## Defined in + +types.ts:123 diff --git a/versioned_docs/version-v1.7/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.7/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..3e24994833 --- /dev/null +++ b/versioned_docs/version-v1.7/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +# TotalSplitPayload + +> **TotalSplitPayload**: `object` + +Split Proxy Params + +### Type declaration + +| Name | Type | Description | Defined in | +| -------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)\[] | The split recipients addresses and splits. | types.ts:136 | +| `ObolRAFSplit`? | `number` | Split percentageNumber allocated for Obol protocol development fee, minimum is 1%. | types.ts:139 | +| `distributorFee`? | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | types.ts:142 | +| `controllerAddress`? | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | types.ts:145 | + +### Defined in + +types.ts:134 diff --git a/versioned_docs/version-v1.7/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.7/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..5368c6e179 --- /dev/null +++ b/versioned_docs/version-v1.7/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# walkthroughs + diff --git a/versioned_docs/version-v1.7/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.7/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.7/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_docs/version-v1.8/README.md b/versioned_docs/version-v1.8/README.md new file mode 100644 index 0000000000..1cf9800b4e --- /dev/null +++ b/versioned_docs/version-v1.8/README.md @@ -0,0 +1,8 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "Introduction" +slug: /learn/readme +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..27650c3586 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# advanced + diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/add-operators.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/add-operators.md new file mode 100644 index 0000000000..bfd1a4b5a1 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/add-operators.md @@ -0,0 +1,99 @@ +--- +description: "Add operators to your existing distributed validator cluster using the charon alpha edit add-operators command." +sidebar_label: "Adding Operators" +slug: /advanced-and-troubleshooting/advanced/add-operators +--- + +# Adding Operators + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can add operators to your cluster using the `charon alpha edit add-operators` command. This operation keeps all distributed validator public keys unchanged whilst adding new operators to the cluster. + +## Prerequisites + +1. Review the `edit add-operators` command [CLI reference](../../learn/charon/charon-cli-reference.md#add-operators-to-a-cluster). +2. **For existing operators**: Keep the DV node running during the process and ensure you have a copy of the current [cluster lock file](../../learn/charon/cluster-configuration#cluster-lock-file) and validator private key shares. +3. **For new operators**: Obtain a copy of the existing cluster lock file from the existing operators and have your Charon ENR private key file ready. +4. Obtain the Charon ENR addresses of all new operators being added to the cluster. + +:::info +The command uses a different set of p2p-relays to `charon run` to avoid conflicts with your running cluster. +::: + +## Adding Operators Process + +The examples below demonstrate adding new operators to an existing cluster. All existing operators must run this command, along with the new operators being added. + +### For Existing Operators + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --output-dir=/opt/charon/output +``` + +### For New Operators + +New operators being added should run the same command but only need to provide their private key file and the cluster lock file (they won't have validator keys yet): + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --output-dir=output --lock-file=cluster-lock.json --private-key-file=charon-enr-private-key + +# Or, if you prefer running it in Docker +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:latest alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --private-key-file=/opt/charon/charon-enr-private-key --lock-file=/opt/charon/cluster-lock.json --output-dir=/opt/charon/output +``` + +:::info +To add multiple operators at once, provide a comma-separated list: `--new-operator-enrs=enr:-JG4QH...,enr:-JG4QK...,enr:-JG4QL...` +::: + +This command will create a new cluster configuration with the additional operators whilst keeping all validator public keys unchanged. The new configuration will be saved in the `output` directory. + +## Making the DV Stack Use the New Configuration + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +1. To start using the new configuration (with the added operators), stop the current Charon and validator client instances: + +```bash +# Stop the containers +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +# Put the original artifacts in a backup location +mv .charon .charon-backup +# Copy the output from the add-operators command into the location of the original files +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +# Restart charon and the validator client with the new data +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` and recognise all validators in the cluster with the updated operator set. + +:::warning +All existing operators must fully shut down their cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the expanded operator set can begin operating. Unlike add-validators, this is not a gradual migration. + +It is advisable to shut the cluster down for at least two epochs, to minimise any risk of unintended double signing during the controlled restart. +::: + +## Current Considerations + +- The new cluster configuration will not yet be reflected on the Obol Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +- All operators (both existing and new) must participate in the add-operators ceremony for it to complete successfully. +- The cluster's threshold value remains unchanged after adding operators because the existing set of operators already possesses enough shares to create full signatures. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/add-validators.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/add-validators.md new file mode 100644 index 0000000000..6e42339ad2 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/add-validators.md @@ -0,0 +1,77 @@ +--- +description: "Add validators to your existing distributed validator cluster using the charon alpha edit add-validators command." +sidebar_label: "Adding Validators" +slug: /advanced-and-troubleshooting/advanced/add-validators +--- + +# Adding Validators + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can add validators to your cluster using the `charon alpha edit add-validators` command. The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) and assumes a Lodestar validator, but the process is similar for other setups. + +## Prerequisites + +1. Review the `edit add-validators` command [CLI reference](../../learn/charon/charon-cli-reference.md#add-validators-to-a-cluster). +2. Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares (or use `--unverified` if validator keys are not accessible). + +:::info +The command uses a different set of p2p-relays to `charon run` to avoid conflicts with your running cluster. +::: + +## Adding Validators Process + +The examples below are for adding 10 validators. You can use them with any number of validators you would like to add. Run the following command to collectively generate and add 10 new validators with other node operators (similar to DKG): + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --output-dir=/opt/charon/output +``` + +This command will create a new cluster configuration that includes both existing and new validators. It will also generate the necessary keys for the new validators and deposit data files. The new configuration will be saved in the `output` directory. + +## Making the DV Stack Use the New Validators + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +1. To start using the new configuration (with the added validators), stop the current Charon and validator client instances: + +```bash +# Stop the containers +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +# Put the original artifacts in a backup location +mv .charon .charon-backup +# Copy the output from the add-validators command into the location of the original files +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +# Restart charon and the validator client with the new data +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` and recognise all validators in the cluster. + +:::info +Steps 1–3 must be performed independently by all node operators, likely at different times. During this process, some nodes will use the old configuration and others the new one. Once the number of upgraded nodes reaches the BFT threshold, the newly added validators will begin participating in the cluster. +::: + +## Current Considerations + +- The new cluster configuration will not be reflected on the Obol Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster under a different identifier. +- If Charon has no access to the existing validator keys (for example, if they're stored in a remote KeyManager), you must use the `--unverified` flag. This flag allows the addition to proceed but skips hashing and signing the new cluster lock data. However when using cluster artifacts created with this flag, you must start `charon run` with the `--no-verify` flag or set the `CHARON_NO_VERIFY=true` environment variable. +- If you use different validator clients, review the keys import script. The old keys in `.charon/validator_keys` remain unchanged, so verify that importing the same keys will not disrupt the validator client's state. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..91890c82c5 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 version-controlled 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 `tempo`. 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 +``` diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md new file mode 100644 index 0000000000..5a66ca25d4 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md @@ -0,0 +1,80 @@ +--- +description: "Prepare an alternative deposit for an unused validator" +sidebar_label: "Alter Withdrawal Addresses" +slug: /advanced-and-troubleshooting/advanced/alter-withdrawal-addresses +--- + +# Altering a Withdrawal Address for an unused validator + +:::warning +Please take care when changing a withdrawal address for an inactivated validator. Activating a validator that exits to a withdrawal address you don't control likely means your funds are lost. + +Also be careful as to the trustworthiness of the original withdrawal address. They [could attempt to front-run](https://medium.com/immunefi/rocketpool-lido-frontrunning-bug-fix-postmortem-e701f26d7971) the alternative deposit, and end up receiving the new depositor's funds to their withdrawal address. +::: + +On occasion it can be useful to be able to change the withdrawal address specified for an already created but unused distributed validator. For example if they are unneeded extra capacity, or if the withdrawal address to be used was not known at cluster creation time and a trusted placeholder address was used instead. The `charon deposit` commands allow you to sign alternative deposit messages for **inactive validators** with the help of the Obol [API](../../api/what-is-this-api.md). + +:::info +If you want to change the withdrawal address of a running validator, consider a validator [consolidation](./operator-rotation.md) instead. +::: + +## Sign an alternative deposit message + +A threshold of operators must decide which public keys they are changing the withdrawal address for, and what the new withdrawal address will be. Then each run the `charon deposit sign` command with their partial private keys and the appropriate (identical) flags. + +**Single public key** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" +``` + +:::info +`validator-public-keys` are the distributed validator public keys for which the alternative deposit data should be signed (find them in your cluster_lock.json file in the `distributed_validator_public_keys` mapping or on the DV Launchpad). `withdrawal-addresses` are the new withdrawal address(es) for which the new deposit data should be signed. There should either be the same amount as `validator-public-keys` specified, or a single address that will be used for all public keys specified. + +Optionally, users can also specify multiple different `deposit-amounts` (defaults to only `32`) to be prepared. +::: + +**Multiple public keys, multiple withdrawal addresses** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045,0x1db3439a222c519ab44bb1144fc28167b4fa6ee6" +``` + +**Multiple public keys, single withdrawal address** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" +``` + +## Fetch full deposit data + +After a threshold of operators have submitted partial alternative deposits, a full aggregated deposit message can be fetched from Obol API. + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit fetch \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ +``` + +:::info +`validator-public-keys` are the validator public keys for which the new deposit data should be fetched. +::: + +After a successful fetch the new deposit data files are saved in `.charon/deposit-data-.json`. + +If there are not enough partial signatures, an error message will be returned. + +```sh +17:18:40.771 ERRO cmd Application failed to start: fetch full deposit data from Obol API: not enough partial signatures to meet threshold {"submitted_public_keys": "[0x8677e2014a173f72b3d4528893cb01881549631c2a39d90d7c19c230299a57440e73c82c7daf1d72713b1e26e42bae99]", "submitted_public_keys_length": 1, "required_threshold": 3} +``` + +This deposit message file can be used with a deposit interface, to activate the validator on the Ethereum deposit contract. + +:::danger +Please take care not to mistakenly activate the old `deposit-data.json` file when the cluster was originally created, containing the withdrawal address you hope to replace. If you activate a validator with a withdrawal address you don't control, your funds are likely lost. +::: \ No newline at end of file diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/beacon-node-authentication.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/beacon-node-authentication.md new file mode 100644 index 0000000000..ec63bbee2f --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/beacon-node-authentication.md @@ -0,0 +1,39 @@ +--- +description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control." +sidebar_label: "Beacon node authentication" +slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication +--- + +# Beacon node authentication + +## HTTP Basic Access Authentication + +If you want to use Charon with an [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic ` where `Authorization` will be the header key and `Basic ` will be the header value. The `` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`. + +:::warning +These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node. +::: + +## Usage example + +Suppose we have an HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command: + +``` +echo -n "john:doe" | base64 +``` + +Then you could pass the flag to your Charon instance like this: + +``` +charon run --beacon-node-headers="Authorization=Basic am9objpkb2U=" +``` + +Or you could specify it as an environment variable like this: + +``` +CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U=" +``` + +:::info +Note that 'Authorization' is followed with an `=` rather than the usual `:`. +::: diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/client-swap.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/client-swap.md new file mode 100644 index 0000000000..5109afea7c --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/client-swap.md @@ -0,0 +1,186 @@ +--- +description: "Swap EL, CL, VC and MEV clients in the stack." +sidebar_label: "Swapping Clients" +slug: /advanced-and-troubleshooting/advanced/client-swap +--- + +# Client swap + +If you are using CDVN, the default stack is: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | --------- | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | + +However, to achieve greater resilience through client diversity, it is preferred to run a variety of clients across your cluster, ideally ensuring no single EL/CL/VC runs on one third of the nodes or more. CDVN supports changing from the default clients. + +Currently supported client options are: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | ------------ | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | +| Reth | Grandine | | Nimbus | Commit boost | +| | Lodestar | | Prysm | | +| | Teku | | Teku | | + +For support between different combinations, refer to Charon's compatibility matrix, found in the [prepare section of the docs](../../run-a-dv/prepare/how_where_dvs.md) or under [release notes](https://github.com/ObolNetwork/charon/releases/) for each release. + +:::info +As CDVN natively supports more clients, the number of possible combinations grows quickly. +We test extensively, but cannot guarantee the performance of all possible client combos. +If you run a mixed-client cluster, monitor performance and be ready to swap to another client if you observe issues. +::: + +:::info +There is currently an incompatibility between validator clients that may cause attestation aggregation duties to fail. Aggregation duties are not economically rewarded nor punished for their completion. + +To ensure aggregations succeed; have at least threshold of nodes in the cluster running one of Lodestar, Lighthouse, and Nimbus, or alternatively; have a threshold of nodes in the cluster running one of Teku and Prysm. This incompatibility will be remediated in upcoming client releases. +::: + +:::warning +**Lodestar's validator** client's default behaviour is to skip the next slot if it fails an attestation or aggregation. This can impact your cluster's performance, particularly if you have more than the fault tolerance threshold of your cluster running Lodestar's validator client, and many validators running in the cluster. + +If your cluster is not successfully aggregating, you should ideally swap to a set of compatible validator clients listed above, along with ensuring your clients have the appropriate [`--distributed` flag](../troubleshooting/client_configurations.md) set to enable distributed aggregation mode. Failing that, you can add the flag `--slotSkip false` to your `lodestar vc` process, (requires lodestar to be version `v1.37.0` and newer) or set `VC_LODESTAR_DISABLE_SLOT_SKIP=true` in your `.env` file if you're using (L)[CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node). This disables the slot skipping feature. +::: + +## Choosing clients in fresh cluster + +In order to choose which clients to use in a new cluster, simply leave uncommented (only) the desired `EL`, `CL`, `MEV` or `VC` variables in the `.env` file. There must be only one client per component. The cluster will use the respective client for each component. + +## Swapping clients in an already running cluster + +:::warning +For ([L](https://github.com/obolNetwork/lido-charon-distributed-validator-node))[CDVN](https://github.com/obolNetwork/charon-distributed-validator-node) users who created their `.env` file before the release of charon `v1.8.0`, there are breaking changes between then and the current multi-client `.env` file setup. +The minimal addition to an older version of the `.env` file compatible with the current versions of the repos is to add `COMPOSE_PROFILES=el_nethermind,cl_lighthouse,dv_charon,vc_lodestar,mev_mevboost` to your existing `.env` file. +Some environment variables were renamed in order to be client-agnostic. **If you had set these environment variables to custom values in your `.env`, you need to set the new variables to your custom values**. They serve the same purpose. + +| Old | New | +|-------------------------------|--------------------------------- | +| NETHERMIND_PORT_P2P | EL_PORT_P2P | +| NETHERMIND_IP_HTTP | EL_IP_HTTP | +| NETHERMIND_PORT_HTTP | EL_PORT_HTTP | +| NETHERMIND_IP_ENGINE | EL_IP_ENGINE | +| NETHERMIND_PORT_ENGINE | EL_PORT_ENGINE | +| LIGHTHOUSE_PORT_P2P | CL_PORT_P2P | +| LODESTAR_PORT_METRICS | VC_PORT_METRICS | +| MEVBOOST_TIMEOUT_GETHEADER | MEV_TIMEOUT_GETHEADER | +| MEVBOOST_TIMEOUT_GETPAYLOAD | MEV_TIMEOUT_GETPAYLOAD | +| MEVBOOST_TIMEOUT_REGVAL | MEV_TIMEOUT_REGVAL | +| MEVBOOST_RELAYS | MEV_RELAYS | +| NETHERMIND_PROMTAIL_MONITORED | EL_NETHERMIND_PROMTAIL_MONITORED | +| LIGHTHOUSE_PROMTAIL_MONITORED | CL_LIGHTHOUSE_PROMTAIL_MONITORED | +| LODESTAR_PROMTAIL_MONITORED | VC_LODESTAR_PROMTAIL_MONITORED | +| MEV_BOOST_PROMTAIL_MONITORED | MEV_MEV_BOOST_PROMTAIL_MONITORED | + +::: + +1. Copy the new `.env.sample.` file to `.env`. +2. Comment or uncomment your preferred Execution, Consensus, Validator, and MEV clients and save the file. +3. Stop the existing cluster that uses the old environment file. + +```sh +docker compose --profile "" down +``` + +3. Start the node again to pick up the changes to the `.env` file. + +```sh +docker compose up -d +``` + +Your node should start up with the new clients. + +### Swap Consensus layer + +:::info +The code snippets under those steps are assuming you are swapping from Lighthouse CL to Grandine CL and you. +::: + +1. Stop the existing consensus layer client container. + +:::info +If you do not want to experience downtime while the new beacon node is syncing, you can set a fallback beacon node for Charon (`CHARON_FALLBACK_BEACON_NODE_ENDPOINTS` env variable) that will be used while the new BN is syncing. +Note that you need to restart Charon as well in order for it to take effect. +::: + +```sh +docker compose down cl-lighthouse +``` + +1. Comment out the currently set `CL` environment variable in `.env` (i.e.: `CL=cl-lighthouse` -> `#CL=cl-lighthouse`). Uncomment the desired CL (i.e.: `#CL=cl-grandine` -> `CL=cl-grandine`). + +2. Start the new consensus layer client container. + +```sh +docker compose up cl-grandine -d +``` + +4. Restart Charon in order to update the CL client it's querying. + +```sh +docker compose down charon +docker compose up charon -d +``` + +5. After the new consensus layer client is synced and you are assured the new setup is working, you can delete the previous CL client's data in order to save resources. + +```sh +rm -rf ./data/lighthouse +``` + +### Swap Validator client + +:::info +The code snippets under those steps are assuming you are swapping from Lodestar VC to Teku VC. +::: + +1. Stop the existing validator client container. + +```sh +docker compose down vc-lodestar +``` + +2. Comment out the currently set `VC` environment variable in `.env` (i.e.: `VC=vc-lodestar` -> `#VC=vc-lodestar`). Uncomment the desired VC (i.e.: `#VC=vc-teku` -> `VC=vc-teku`). + +3. Start the new validator client container. + +```sh +docker compose up vc-teku -d +``` + +4. After the new validator client is started and you are assured the new setup is working, you can delete the previous VC's data in order to save resources + +```sh +rm -rf ./data/lodestar +``` + +### SWAP MEV client + +:::info +The code snippets under those steps are assuming you are swapping from MEV Boost to Commit Boost and you are using Lighthouse CL. +::: + +:::info +If switching to Commit Boost, you will need to copy a Commit Boost TOML config `commit-boost/config.toml.sample.` to `commit-boost/config.toml`, as it does not support `.env` configurations yet. Make sure the configuration matches what you have had set for mev-boost, in terms of relays and timeouts. +::: + +1. Stop the existing MEV client container. + +```sh +docker compose down mev-mevboost +``` + +2. Comment out the currently set `MEV` environment variable in `.env` (i.e.: `MEV=mev-mevboost` -> `#MEV=mev-mevboost`). Uncomment the desired MEV (i.e.: `#MEV=mev-commitboost` -> `MEV=mev-commitboost`). + +3. Start the new MEV client container. + +```sh +docker compose up mev-commitboost -d +``` + +4. Restart the beacon node in order to update the MEV it's querying. + +```sh +docker compose down cl-lighthouse +docker compose up cl-lighthouse -d +``` diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..6a3e28c8a6 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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 {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client {#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. + +```sh +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 Hoodi +const obol = new Client({ chainId: 560048 }, signer); +``` + +### Propose the cluster {#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. + +```sh +// 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://hoodi.launchpad.obol.org/dv?configHash=${configHash} to complete the key generation process` +); +``` + +### Invite the Operators to complete the DKG {#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://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](../../run-a-dv/start/create-a-dv-with-a-group.mdx) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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 {#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. + +```sh +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 {#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. + +```sh +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 {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/custom-graffiti.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/custom-graffiti.md new file mode 100644 index 0000000000..567abf7ad0 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/custom-graffiti.md @@ -0,0 +1,20 @@ +--- +description: "Add custom graffiti to your block proposals" +sidebar_label: "Custom Graffiti" +slug: /advanced-and-troubleshooting/advanced/custom-graffiti +--- + +# Custom Graffiti + +By default, Charon adds a `charon/-` graffiti to all block proposals. This can be customized using the `--graffiti` and `--graffiti-disable-client-append` CLI flags. + +The `--graffiti` flag accepts either: + +* A single string, which will be used by all validators, or +* A comma-separated list of strings, allowing each validator to have a unique graffiti (one string per validator). + +When possible, Charon automatically appends an Obol signature (`OB`) and the specific consensus client type used (``) to the end of the custom graffiti. This behavior can be disabled by setting the `--graffiti-disable-client-append` flag. + +:::info +The graffiti field in block proposals has a maximum size of 32 bytes. +::: diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..b63202d379 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](../../run-a-dv/prepare/test-a-cluster.mdx#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [Ultrasound Relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. If you are using [Titan Relay](https://titanrelay.xyz), you can check their API by running `curl https://titanrelay.xyz/relay/v1/data/validator_registration?pubkey=0x123..456` with the public key of a validator in your cluster. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/enable-tls-protocol.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/enable-tls-protocol.md new file mode 100644 index 0000000000..c822a27225 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/enable-tls-protocol.md @@ -0,0 +1,37 @@ +--- +description: "Enable the TLS protocol to secure HTTPS requests made by the Validator Client to Charon." +sidebar_label: "Enable TLS Protocol" +slug: /advanced-and-troubleshooting/advanced/enable-tls-protocol +--- + +# Enable TLS protocol + +## Securing VC to Charon communication + +To secure the communication between the Validator Client and Charon, you can enable the TLS protocol in Charon's HTTP server. This only affects [Beacon API](https://ethereum.github.io/beacon-APIs/) endpoints and not debug/metrics endpoints. As an operator of the node, you need to have a TLS certificate and a private key that signed this certificate or CSR. Then you need to configure Charon to use them. +## Usage example + +Suppose we don't have a TLS certificate and a key yet. We can create a self-signed certificate and a key using OpenSSL: + +``` +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +Then you could pass the flags to your Charon instance like this: + +``` +charon run --vc-tls-cert-file cert.pem --vc-tls-key-file key.pem +``` + +Charon accepts a certificate in PEM or CRT formats and the private key in PEM or DER formats. + +Also you can specify these parameters as environment variables like this: + +``` +CHARON_VC_TLS_CERT_FILE="cert.pem" +CHARON_VC_TLS_KEY_FILE="key.pem" +``` + +On the Validator Client (VC) side, no additional configuration is typically required. The VC will automatically use the TLS protocol when communicating with Charon. However, if the TLS certificate is signed by a custom or non-standard certificate authority (CA), you may need to configure the VC to trust this CA. This can usually be achieved by adding the CA's certificate to the trusted certificate store on the machine running the VC. + +If necessary, you can also enable `insecure` mode in the VC configuration to bypass TLS verification. Note that this approach is not recommended for production environments as it compromises security. Detailed instructions for configuring specific Validator Clients are beyond the scope of this article. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md new file mode 100644 index 0000000000..7f301659c6 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md @@ -0,0 +1,13 @@ +--- +description: "Add fallback beacon nodes to use when primary beacon node fails" +sidebar_label: "Fallback Beacon Nodes" +slug: /advanced-and-troubleshooting/advanced/fallback-beacon-nodes +--- + +# Fallback beacon nodes + +Charon allows specifying multiple beacon node URL endpoints. It sends requests to all specified endpoints simultaneously and proceeds with the first response received. This approach improves reliability but increases the load on the beacon nodes. + +To mitigate this additional load, Charon supports configuring a fallback list of beacon nodes. These fallback nodes are only used if all primary beacon nodes fail to respond. This allows operators to designate less critical or public beacon nodes as a backup option, without impacting them under normal conditions. + +To configure fallback beacon nodes, provide a comma-separated list of beacon node URLs using the `--fallback-beacon-node-endpoints` CLI flag. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/nicknames.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/nicknames.md new file mode 100644 index 0000000000..9606a46788 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/nicknames.md @@ -0,0 +1,18 @@ +--- +description: "Add a nickname to your Charon node" +sidebar_label: "Nicknames" +slug: /advanced-and-troubleshooting/advanced/nicknames +--- + +# Nicknames + +By default, Charon assigns each node a name by combining a random adjective with a random name from a predefined list. While these names are human-readable, they are not easily memorable or personalised for operators. + +You can set a personalised nickname for your Charon node by using the `--nickname` CLI flag followed by the desired string. This nickname is shared with other Charon nodes in the same cluster and included as a label in your Prometheus metrics. + +Nicknames can serve various purposes, such as providing a more memorable identifier, including a Discord ID for alerting, or adding a website URL for publicity. + + + + + diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/operator-rotation.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/operator-rotation.md new file mode 100644 index 0000000000..658ff4045c --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/operator-rotation.md @@ -0,0 +1,112 @@ +--- +description: "Validator consolidation workflow for rotating operators in an Obol distributed validator cluster." +sidebar_label: "Operator Rotation" +slug: /advanced-and-troubleshooting/advanced/operator-rotation +--- + +# Operator Rotation + +### Introduction to Operator Rotation using Pectra Validator Consolidation + +Validator consolidation is a new feature for the Ethereum network, introduced with the last **Pectra** network upgrade. It allows a user to "consolidate" multiple validators into a single, new validator. + +- Consolidations can only be performed when the source validator has 0x01 or 0x02 withdrawal credentials and the target validator must be 0x02. The consolidation transaction must be sent from the withdrawal address defined in the source credentials. The target withdrawal credentials can be any address of choice. +- This process transfers the staked ETH from the old validators to the new one while the stake never leaves the beacon chain. The only partial downtime for the source validator is the standard 27-hour waiting period on the beacon chain before the withdrawal. When compared to fully exiting and re-depositing, consolidation avoids the sweep delay required in that option. + +> [!NOTE] +> Future direction (in development): We’re building toward full cluster mutability so operators can react quickly to real-world events. That includes resharing fresh key material across the cluster if there’s ever a security concern, adding new operators to reach full Byzantine fault tolerance, and removing operators who aren’t meeting performance expectations. The goal is to make these changes possible without exiting or consolidating validators. The forthcoming tooling will guide the cluster through a coordinated workflow and produce a fresh set of operator files ready for cutover when you’re comfortable switching over. +--- + +### Guide: Operator Rotation in an Obol Cluster via Validator Consolidation + +Validator consolidation enables a safe and efficient way to perform operator rotation in an Obol cluster. This is achieved by transferring staked ETH directly from a **source cluster** (source validators with its original operators) to a **target cluster** (target validators with a new set of operators). Operator rotation can be classified into several different scenarios: + +- Source and target cluster validators have the same withdrawal address that is an EOA (wallet address) or a Safe contract. +- Source and target cluster validators have different withdrawal addresses but they are still EOAs. +- Source and target cluster validators have the same OVMs as withdrawal addresses. +- Source and target cluster validators have different OVMs as withdrawal addresses. Source can be an OVM and withdrawal can be an EigenPod/EOA/Safe or vice versa. + +In this guide, we focus on source and target validators that have the same withdrawal address that is an EOA or Safe. The other scenarios are actively in development. + +**Pros:** + +- Compared to the Charon native operator rotation, which requires technical knowledge of node operation, must be executed by operators, and is risky for key security when not done properly, consolidation-based operator rotation can be performed by a withdrawal address (who can be a non-operator such as an ETH allocator). +- Very minimal downtime of ~27 hours (256 epochs) on the stake with source validators. Missed rewards are estimated to be around 0.00296 ETH per validator. + +**Cons:** + +- If the number of validators is very high, even a single day of downtime (even though small) can add up. +- Target validators need to be active. This requires an additional 32 ETH for each target validator the cluster wishes to set up. + +This document outlines the step-by-step process for rotating operators in an Obol DVT cluster using the new validator consolidation feature. This guide assumes you are starting with a source cluster with four existing operators and want to consolidate their validators into a new target cluster with four new operators. + +### 1. Prepare the Target Cluster + +- **Create a New Cluster:** As the user, first create a new Obol cluster for four new operators of your choice. More details can be found [here](../../run-a-dv/start/create-a-dv-with-a-group.mdx). +- **Set Withdrawal Address:** Set the withdrawal address for this new cluster to be the same EOA address you used for the source cluster. In future this can be changed to a withdrawal address of your choice. +- **Deploy a New Splitter:** Deploy a new splitter contract dedicated to the new operators of the target cluster. +- **Configure Validators:** Ensure the validators in the new cluster are configured as **compounding validators** with the `0x02` credential type. To enable this make sure to turn the compound toggle on or use the `--compounding` flag if using the CLI directly. + +![Compounding validator configuration](/img/gitbook/operator-rotation-compounding.png) + +- **Run Nodes:** Start the Charon nodes for all operators in the new target cluster. Make sure all the nodes are healthy and ready for deposits. More details [here](../../run-a-dv/running/monitoring.md). +- **Activate Validators:** Activate the target validators by depositing 32 ETH for each. More details [here](../../run-a-dv/running/activate-a-dv.md). The image shows a new operator `0x493...9b1`. + +![Target validator activation view](/img/gitbook/operator-rotation-activate.png) + +### 2. Finalize the Source Cluster + +- Have a source cluster ready. Make sure you are connected with the correct withdrawal address. In this case, the operator [`0x28eC4c075DF60535DDE5e2788C34B1961c99474c`](https://hoodi.launchpad.obol.org/operator/0x28eC4c075DF60535DDE5e2788C34B1961c99474c/) is also the withdrawal address. + +![Source cluster withdrawal operator](/img/gitbook/operator-rotation-source-withdrawal.png) + +![Source cluster validator list](/img/gitbook/operator-rotation-source-dashboard.png) + +- **Distribute Rewards:** Before proceeding, distribute all pending rewards from the source cluster's splitter contract to ensure all financial obligations are settled with the original operators. The rewards should be 0 after rewards are distributed and claimed. + +![Splitter rewards distribution](/img/gitbook/operator-rotation-rewards.png) + +### 3. Initiate the Consolidation + +- **Access the Migration Tool:** Navigate to the Obol Launchpad migration page by using a URL such as `https://hoodi.launchpad.obol.org/migrate/?withdrawalAddress=your_withdrawal_address`. Alternatively, click the **Migrate** button on a target validator's page within the target cluster dashboard. This **Migrate** button is only clickable for validators where the connected address is the withdrawal address. Make sure the correct address is connected. + +![Launchpad migrate action](/img/gitbook/operator-rotation-migrate.png) + +- **Select Validators:** On the migration page, select the source validators from the original cluster that you wish to consolidate. + + + +- **Confirm and Consolidate:** Click the **Migrate** button to send the consolidation request. + + +![Target withdrawal address view](/img/gitbook/operator-rotation-target-withdrawal.png) + +### 4. Post-Consolidation Actions + +> [!INFO] +> Screenshots are for reference only, your validator balances and performance will differ. + +- **Source Validator Exit:** Once the consolidation request is processed by the Ethereum network, the source validators will be set to exit automatically. On [beaconcha.in](https://beaconcha.in) the validator pubkey will show an **exiting** status with consolidation in progress. + +![Beaconcha.in validator showing exiting status](/img/gitbook/operator-rotation-beaconcha-exiting.png) + +![Launchpad validator exit notification](/img/gitbook/operator-rotation-launchpad-exit.png) + +- **Waiting Period:** After the exit is complete, the validator enters a ~27 hour waiting period (256 epochs). In the example below the validator is marked **exited** while the withdrawable epoch remains in the future (43257). Once the withdrawable epoch is reached, ETH will be consolidated to the target validator. + +![Beaconcha.in withdrawable epoch countdown](/img/gitbook/operator-rotation-beaconcha-withdrawable.png) + +- **ETH Transfer:** After the waiting period, the staked ETH from the source validators is automatically consolidated and credited to the target validators in the new cluster. + +![Target validator credited after consolidation](/img/gitbook/operator-rotation-target-credited.png) + +- **Wind Down Source Clusters:** Once the source validators have fully exited and funds have settled with the target cluster, you can wind down the original operators. + +![Cluster dashboard ready for wind down](/img/gitbook/operator-rotation-wind-down.png) + +This process ensures a seamless and secure operator rotation, leveraging the efficiency of validator consolidation to minimize downtime and avoid a lengthy manual withdrawal process. + +**Example clusters used in screenshots:** + +- Target cluster: [0x15d1…9e32](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x15d113c8c3e3ca1ec24bbdd5c5d8f9065c36f07d9d70c13e9a4efba8a35b9e32) +- Source cluster: [0xF321…2885](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0xF321443022ABA165FF5635CF71DC9DA0FC29EE91D03117055E97A1F92B5C2885) diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/partial-deposit.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/partial-deposit.md new file mode 100644 index 0000000000..49d728055c --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/partial-deposit.md @@ -0,0 +1,64 @@ +--- +description: "Submit and fetch (partial) deposits." +sidebar_label: "The need of partial deposits" +slug: /advanced-and-troubleshooting/advanced/partial-deposit +unlisted: true +--- + +# The need of partial deposits + +Some operators opt to create a big cluster, even though only a subset of the validators will be activated in the short term. +When there is enough business incentive to activate more validators from the cluster, the business cases might have changed and a different withdrawal addresses to be required for those new validators. + +Changing the signed deposit data post- cluster creation and pre- validator activation can be useful in such scenarios. Threshold of nodes need to agree and sign the new deposit data, then the signatures are aggregated and the new deposit data message is created. For convenience, Obol API is used for that purpose. + +## Sign partial deposit data + +First a partial deposit data signature from the current Charon node should be signed and broadcasted to Obol API. + +`validator-public-keys` are the validator public keys for which the new deposit data should be signed. +`withdrawal-addresses` are the new addresses for which the new deposit data should be signed. They should either be the same amount as `validator-public-keys` or a single one, that will be used for all keys. +Optionally, users can also specify different multiple `deposit-amounts` (defaults to only `32`). + +**Single public key** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0x0100000000000000000000000d941218c10b055f0907fe1bbe486ccdaa7e332b" +``` + +**Multiple public keys, multiple withdrawal addresses** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0x0100000000000000000000000d941218c10b055f0907fe1bbe486ccdaa7e332b,0x0100000000000000000000000e941218c10b055f0907fe1bbe486ccdaa7e332b" +``` + +**Multiple public keys, single withdrawal address** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0x0100000000000000000000000d941218c10b055f0907fe1bbe486ccdaa7e332b" +``` + +## Fetch full deposit data + +After a threshold of operators have submitted partial deposits, a full deposit can be fetched from Obol API. + +`validator-public-keys` are the validator public keys for which the new deposit data should be fetched. + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 deposit fetch \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ +``` + +After a successful fetch the new deposit data files are saved in `.charon/deposit-data-`. + +If there are not enough partial signatures, an error message will be returned. + +```sh +17:18:40.771 ERRO cmd Application failed to start: fetch full deposit data from Obol API: not enough partial signatures to meet threshold {"submitted_public_keys": "[0x8677e2014a173f72b3d4528893cb01881549631c2a39d90d7c19c230299a57440e73c82c7daf1d72713b1e26e42bae99]", "submitted_public_keys_length": 1, "required_threshold": 3} +``` diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..ba3ab82159 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.8.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. +::: diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..c7346f3925 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,110 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +:::info +Starting with Charon v1.8.0, you may not need to manually prepare the keystore files as described below. Charon can recursively search for keystore files in the specified directory and attempt to match the corresponding password files. The only case where this does not work is when you specify an exact list of withdrawal addresses; in that case, you must prepare the files manually and ensure the keystore indices match the order of the specified withdrawal addresses. +::: + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.8.0 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet \ + --publish +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/recreate-private-keys.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/recreate-private-keys.md new file mode 100644 index 0000000000..98a9ac3b9a --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/recreate-private-keys.md @@ -0,0 +1,124 @@ +--- +description: "Create new private key shares for your existing distributed validator cluster using the charon alpha edit recreate-private-keys command." +sidebar_label: "Recreating Private Keys" +slug: /advanced-and-troubleshooting/advanced/recreate-private-keys +--- + +# Recreating Private Keys + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can recreate the private key shares for your cluster using the `charon alpha edit recreate-private-keys` command. This operation creates new private key shares to replace the existing validator private keys whilst retaining the same operator identities and validator public keys. + +## When to Use This Feature + +You might need to recreate private key shares in several scenarios: + +- **Security concerns**: If you suspect that private key shares may have been compromised +- **Key rotation**: As part of regular security practices to rotate cryptographic material +- **Recovery**: After a security incident where you want to refresh all key material +- **Compliance**: Meeting organisational policies that require periodic key rotation + +:::info +This operation maintains the same validator public keys, so your validators remain registered on the beacon chain without any changes. Only the underlying private key shares held by operators are refreshed. +::: + +## Prerequisites + +1. Review the `edit recreate-private-keys` command [CLI reference](../../learn/charon/charon-cli-reference.md#recreate-private-key-shares). +2. Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares. +3. All operators in the cluster must participate in this ceremony. +4. Each operator must have their current validator private key shares available. + +:::info +The ceremony uses a different p2p relay from your running cluster to avoid conflicts. The default relay address is already configured differently, so no special action is required. +::: + +## Recreating Private Keys Process + +All operators must run this command simultaneously. The ceremony will coordinate between all operators to generate new private key shares. + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit recreate-private-keys --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit recreate-private-keys --output-dir=/opt/charon/output +``` + +This command will: +1. Use the existing cluster configuration and operator identities +2. Generate new private key shares for all validators +3. Create a new cluster lock file with updated key shares +4. Save the new configuration in the `output` directory + +:::info +The ceremony requires all operators to participate. If any operator is unavailable, the ceremony cannot complete. +::: + +## Making the DV Stack Use the New Keys + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +:::danger +**Critical Security Step**: All operators must coordinate to switch to the new keys at approximately the same time to avoid validation failures. Plan a maintenance window and communicate clearly with all operators. +::: + +1. To start using the new keys, stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` with the recreated private key shares. + +:::warning +All operators must fully shut down their existing cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the recreated private keys can begin operating. Steps 1–3 must be performed by all node operators within a coordinated maintenance window to minimise downtime. +::: + +## Verifying the New Configuration + +After all operators have restarted with the new keys, verify that: + +1. All Charon nodes are connected and healthy +2. The cluster is successfully producing attestations +3. No error messages appear in the logs related to signature verification + +```bash +# Check Charon logs +docker compose logs -f charon + +# Verify cluster health in the monitoring dashboard +# Check that all validators are attesting normally +``` + +## Security Best Practices + +- **Secure deletion**: After successfully transitioning to the new keys and verifying operation, securely delete the old key shares +- **Coordination**: Ensure all operators are prepared and available during the planned maintenance window +- **Communication**: Maintain clear communication channels between all operators throughout the process +- **Backup**: Keep the backup until you've verified that the cluster is operating normally with the new keys for at least several epochs + +## Current Limitations + +- The new cluster configuration will not be reflected on the Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +- All operators must participate in the ceremony; there is no option for partial participation. +- All operators must have their current validator private key shares available for the ceremony to succeed. +- The transition period requires coordination to minimise validator downtime. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/remove-operators.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/remove-operators.md new file mode 100644 index 0000000000..54271aaf56 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/remove-operators.md @@ -0,0 +1,131 @@ +--- +description: "Remove operators from your existing distributed validator cluster using the charon alpha edit remove-operators command." +sidebar_label: "Removing Operators" +slug: /advanced-and-troubleshooting/advanced/remove-operators +--- + +# Removing Operators + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can remove operators from your cluster using the `charon alpha edit remove-operators` command. This operation leaves all validators intact whilst removing specified operators from the cluster. + +## Prerequisites + +1. Review the `edit remove-operators` command [CLI reference](../../learn/charon/charon-cli-reference.md#remove-operators-from-a-cluster). +2. **For remaining operators**: Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares. +3. **For operators being removed**: A copy of the cluster lock file is required to participate in the ceremony (if participating). +4. Identify the Charon ENR addresses of the operators you wish to remove from the cluster. + +:::info +The ceremony uses a different p2p relay from your running cluster to avoid conflicts. The default relay address is already configured differently, so no special action is required. +::: + +## Understanding Fault Tolerance + +Before removing operators, it's crucial to understand your cluster's fault tolerance: + +- **Fault tolerance (f)** = `number of operators - threshold` +- If you're removing **more operators than the fault tolerance**, you must use the `--participating-operator-enrs` flag to specify which operators will participate in the ceremony. + +For example, if your cluster has 4 operators with a threshold of 3 (f=1), removing 2 operators requires specifying at least 3 participating operators. + +## Removing Operators Process + +### Standard Removal (Within Fault Tolerance) + +If you're removing operators within the fault tolerance, all remaining operators can participate automatically: + +```bash +# For remaining operators +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --output-dir=output + +# Docker version +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --output-dir=/opt/charon/output +``` + +### Advanced Removal (Exceeding Fault Tolerance) + +If you're removing more operators than the fault tolerance allows, you must specify participating operators: + +```bash +# For participating operators (both remaining and being removed) +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH...,enr:-JG4QK... --participating-operator-enrs=enr:-JG4QL...,enr:-JG4QM...,enr:-JG4QN... --output-dir=output + +# Docker version +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH...,enr:-JG4QK... --participating-operator-enrs=enr:-JG4QL...,enr:-JG4QM...,enr:-JG4QN... --output-dir=/opt/charon/output +``` + +:::info +When using `--participating-operator-enrs`, you must have at least `threshold` number of operators participating. Operators being removed can participate if explicitly included in this list. +::: + +### For Operators Being Removed + +Operators being removed have two options: + +1. **If participating** (when explicitly included in `--participating-operator-enrs`): Run the same command as other participants with the `--output-dir` flag +2. **If not participating**: Do not run the command at all; simply ignore the ceremony + +```bash +# For removed operators who are participating in the ceremony +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --participating-operator-enrs=enr:-JG4QH...,enr:-JG4QK...,enr:-JG4QL... --private-key-file=.charon/charon-enr-private-key --lock-file=.charon/cluster-lock.json --validator-keys-dir=.charon/validator_keys --output-dir=output +``` + +## Customising the Threshold + +By default, the new threshold is calculated as `ceil(n * 2 / 3)`, where `n` is the new number of operators. You can override this with the `--new-threshold` flag: + +```bash +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --new-threshold=3 --output-dir=output +``` + +:::danger +Using a non-default threshold value decreases security. All operators must use the same value. Only override this if you fully understand the implications. +::: + +## Making the DV Stack Use the New Configuration + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +### For Remaining Operators + +1. Stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +:::warning +All remaining operators must fully shut down their existing cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the reduced operator set can begin operating. +::: + +### For Removed Operators + +Operators who have been removed can safely shut down their nodes after the ceremony completes: + +```bash +docker compose down +``` + +## Current Limitations + +- The new cluster configuration will not be reflected on the Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +- All remaining operators must have valid validator keys to participate in the removal ceremony. +- When removing more operators than the fault tolerance, at least `threshold` operators must participate in the ceremony. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/replace-operator.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/replace-operator.md new file mode 100644 index 0000000000..ac644da66b --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/replace-operator.md @@ -0,0 +1,116 @@ +--- +description: "Replace an operator in your existing distributed validator cluster using the charon alpha edit replace-operator command." +sidebar_label: "Replacing Operator" +slug: /advanced-and-troubleshooting/advanced/replace-operator +--- + +# Replacing an Operator + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can replace an operator in your cluster using the `charon alpha edit replace-operator` command. This operation keeps all validators intact whilst swapping one operator for another in the cluster. + +## Prerequisites + +1. Review the `edit replace-operator` command [CLI reference](../../learn/charon/charon-cli-reference.md). +2. **For continuing operators**: Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares. +3. **For the new operator**: Obtain a copy of the existing cluster lock file from the continuing operators and have your Charon ENR private key file ready. +4. **For the old operator being replaced**: The operator being replaced should NOT participate in the ceremony. +5. Identify the Charon ENR address of the operator you wish to replace and have the new operator's ENR ready. + +:::info +The ceremony uses a different p2p relay from your running cluster to avoid conflicts. The default relay address is already configured differently, so no special action is required. +::: + +## Understanding the Replacement Process + +The replace-operator ceremony performs a one-for-one swap: + +- The **old operator** is completely removed from the cluster and does not participate in the ceremony +- The **new operator** takes over at the same index position as the old operator +- All **continuing operators** must participate with their existing validator keys +- All validator public keys remain unchanged + +This is different from remove-operators followed by add-operators, as it maintains the cluster size and threshold in a single atomic operation. + +## Replacing an Operator + +All continuing operators and the new operator must run this command. The old operator being replaced should NOT run the command. + +### For Continuing Operators + +```bash +# Standard usage +charon alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... --output-dir=output + +# Docker version +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... --output-dir=/opt/charon/output +``` + +### For the New Operator + +The new operator being added should run the same command but only needs to provide their private key file and the cluster lock file (they won't have validator keys yet): + +```bash +# Standard usage +charon alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... --output-dir=output --lock-file=cluster-lock.json --private-key-file=charon-enr-private-key + +# Docker version +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:latest alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... --private-key-file=/opt/charon/charon-enr-private-key --lock-file=/opt/charon/cluster-lock.json --output-dir=/opt/charon/output +``` + +### For the Old Operator Being Replaced + +The old operator **should not participate** in the ceremony. Simply do not run the command. + +:::danger +The old operator's ENR and new operator's ENR must be different. The command will fail if they are the same. +::: + +## Making the DV Stack Use the New Configuration + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +### For Continuing Operators and New Operator + +1. Stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +:::warning +All continuing operators must fully shut down their existing cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the replaced operator can begin operating. +::: + +### For the Old Operator Being Replaced + +The operator who has been replaced can safely shut down their node after the ceremony completes: + +```bash +docker compose down +``` + +## Current Limitations + +- The new cluster configuration will not be reflected on the Launchpad. +- The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +- All continuing operators must have valid validator keys to participate in the replacement ceremony. +- The cluster's threshold value remains unchanged after replacing an operator. +- The new operator's ENR must not already exist in the cluster. +- The old operator's ENR must exist in the current cluster. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..8c80d667f8 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,38 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency and decentralization, you can opt to host your own relay on a separate open and static internet port. + +```shell +# Figure out your public IP +curl v4.ident.me + +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your public IPv4 or DNS hostname + +nano relay/docker-compose.yml + +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +Note that a local `relay/.charon/charon-enr-private-key` file will be created next to `relay/docker-compose.yml` to ensure a persisted relay ENR across restarts. + +A list of publicly available relays that can be used is maintained [here](../security/risks.md). diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/README.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/README.md new file mode 100644 index 0000000000..08d9fd5147 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Security" +slug: /advanced-and-troubleshooting/security +--- + +# security + diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/bug-bounty.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/bug-bounty.md new file mode 100644 index 0000000000..06a57d0d34 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/bug-bounty.md @@ -0,0 +1,181 @@ +--- +description: "Bug Bounty Policy" +sidebar_label: "Obol Bug Bounty Program" +slug: /advanced-and-troubleshooting/security/bug-bounty +--- + +# Obol Bug Bounty Program + +## Overview + +At Obol Labs, we prioritize the security of our distributed validator software and related services. Our Bug Bounty Program is designed to encourage and reward security researchers for identifying and reporting potential vulnerabilities. This initiative supports our commitment to the security and integrity of our products. + +## Participant Eligibility + +Participants must meet the following criteria to be eligible for the Bug Bounty Program: + +- Not reside in countries where participation in such programs is prohibited. +- Be at least 14 years of age and possess the legal capacity to participate. +- Have received consent from your employer, if applicable. +- Not have been employed or contracted by Obol Labs, nor be an immediate family member of an employee, within the last 12 months. + +## Scope of the Program + +Eligible submissions must involve software and services developed by Obol, specifically under the domains of: + +- Charon the DV Middleware Client +- Obol DV Launchpad and Public API +- Obol Splits Contracts +- Obol Labs hosted Public Relay Infrastructure + +Submissions related to the following are considered out of scope: + +- Social engineering +- Rate Limiting (Non-critical issues) +- Physical security breaches +- Non-security related UX/UI issues +- Third-party application vulnerabilities +- The [Obol](https://obol.org) static website or the Obol infrastructure +- The operational security of node operators running or using Obol software + +## Program Rules + +- Submitted bugs must not have been previously disclosed publicly. +- Only first reports of vulnerabilities will be considered for rewards; previously reported or known vulnerabilities are ineligible. +- The severity of the vulnerability, as assessed by our team, will determine the reward amount. See the "Rewards" section for details. +- Submissions must include a reproducible proof of concept. +- The Obol security team reserves the right to determine the eligibility and reward for each submission. +- Program terms may be updated at Obol's discretion. +- Valid bugs may be disclosed to partner protocols within the Obol ecosystem to enhance overall security. + +## Rewards Structure + +Rewards are issued based on the severity and impact of the disclosed vulnerability, determined at the discretion of Obol Labs. + +### Critical Vulnerabilities: Up to $100,000 + +A Critical-level vulnerability is one that has a severe impact on the security of the in-production system from an unauthenticated external attacker, and requires immediate attention to fix. Highly likely to have a material impact on validator private key security, and/or loss of funds. + +- High impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully exfiltrate BLS (not K1) private key material from a threshold number of operators in the cluster. +- Attacker that is not a member of the cluster can achieve the production of arbitrary BLS signatures from a threshold number of operators in the cluster. +- Attacker can craft a malicious cluster invite capable of subverting even careful review of all data to steal funds during a deposit. +- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield +- Direct loss of funds +- Permanent freezing of funds (fix requires hard fork) +- Network not being able to confirm new transactions (Total network shutdown) +- Protocol insolvency + +### High Vulnerabilities: Up to $10,000 + +For significant security risks that impact the system from a position of low-trust and require a significant effort to fix. + +- High impact, medium likelihood +- Medium impact, high likelihood + +Impacts: + +- Attacker that is not a member of the cluster can successfully partition the cluster and keep the cluster offline indefinitely. +- Attacker that is not a member of the cluster can exfiltrate Charon ENR private keys. +- Attacker that is not a member of the cluster can destroy funds but cannot steal them. +- Unintended chain split (Network partition) +- Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments +- RPC API crash affecting projects with greater than or equal to 25% of the market capitalization on top of the respective layer +- Theft of unclaimed yield +- Theft of unclaimed royalties +- Permanent freezing of unclaimed yield +- Permanent freezing of unclaimed royalties +- Temporary freezing of funds +- Retrieve sensitive data/files from a running server: + - blockchain keys + - database passwords + - (this does not include non-sensitive environment variables, open source code, or usernames) +- Taking state-modifying authenticated actions (with or without blockchain state interaction) on behalf of other users without any interaction by that user, such as: + - Changing cluster information + - Withdrawals + - Making trades + +### Medium Vulnerabilities: Up to $2,500 + +For vulnerabilities with a moderate impact, affecting system availability or integrity. + +- High impact, low likelihood +- Medium impact, medium likelihood +- Low impact, high likelihood + +Impacts: + +- Attacker that is a member of a cluster can exfiltrate K1 key material from another member. +- Attacker that is a member of the cluster can denial of service attack enough peers in the cluster to prevent operation of the validator(s) +- Attacker that is a member of the cluster can bias the protocol in a manner to control the majority of block proposal opportunities. +- Attacker can get a DV Launchpad user to inadvertently interact with a smart contract that is not a part of normal operation of the launchpad. +- Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours +- Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network +- Charon cluster identity private key theft +- Rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle +- Charon public relay node is compromised and leads to cluster topologies getting discovered and disrupted +- Smart contract unable to operate due to lack of token funds +- Block stuffing +- Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol) +- Theft of gas +- Unbounded gas consumption +- Redirecting users to malicious websites (Open Redirect) + +### Low Vulnerabilities: Up to $500 + +For vulnerabilities with minimal impact, unlikely to significantly affect system operations. + +- Low impact, medium likelihood +- Medium impact, low likelihood + +Impacts: + +- Attacker can sometimes put a Charon node in a state that causes it to drop one out of every one hundred attestations made by a validator +- Attacker can display bad data on a non-interactive part of the launchpad. +- Contract fails to deliver promised returns, but doesn't lose value +- Shutdown of greater than 10% or equal to but less than 30% of network processing nodes without brute force actions, but does not shut down the network +- Changing details of other users (including modifying browser local storage) without already-connected wallet interaction and with significant user interaction such as: + - Iframing leading to modifying the backend/browser state (must demonstrate impact with PoC) +- Taking over broken or expired outgoing links such as: + - Social media handles, etc. +- Temporarily disabling user to access target site, such as: + - Locking up the victim from login + - Cookie bombing, etc. + +Rewards may be issued as cash, merchandise, or other forms of recognition, at Obol's discretion. Only one reward will be granted per unique vulnerability. + +## The following activities are prohibited by this bug bounty program + +- Any testing on mainnet or public testnet deployed code; all testing should be done on local-forks of either public testnet or mainnet +- Any testing with pricing oracles or third-party smart contracts +- Attempting phishing or other social engineering attacks against our employees and/or customers +- Any testing with third-party systems and applications (e.g. browser extensions) as well as websites (e.g. SSO providers, advertising networks) +- Any denial of service attacks that are executed against project assets +- Automated testing of services that generate significant amounts of traffic +- Public disclosure of an unpatched vulnerability in an embargoed bounty + +## Submission process + +To report a vulnerability, please contact us at security@obol.tech with: + +- A detailed description of the vulnerability and its potential impact. +- Steps to reproduce the issue. +- Any relevant proof of concept code, screenshots, or documentation. +- Your contact information. + +Incomplete reports may not be eligible for rewards. + +## Disclosure and Confidentiality + +Obol Labs will disclose vulnerabilities and the identity of the researcher (with consent) after remediation. Researchers are required to maintain confidentiality until official disclosure by Obol Labs. + +## Legal and Ethical Compliance + +Participants must adhere to all relevant laws and regulations. Obol Labs will not pursue legal action against researchers reporting vulnerabilities in good faith, but reserves the right to respond to violations of this policy. + +## Non-Disclosure Agreement (NDA) + +Participants may be required to sign an NDA for access to certain proprietary information during their research. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/contact.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/contact.md new file mode 100644 index 0000000000..0b4b54d4fd --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/contact.md @@ -0,0 +1,11 @@ +--- +description: "Security details for the Obol Network" +sidebar_label: "Contacts" +slug: /advanced-and-troubleshooting/security/contact +--- + +# Contacts + +Please email security@obol.tech to report a security incident, vulnerability, bug or inquire about Obol's security. + +Also, visit the [obol security repo](https://github.com/ObolNetwork/obol-security) for more details. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/ev-assessment.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/ev-assessment.md new file mode 100644 index 0000000000..969839bde3 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/ev-assessment.md @@ -0,0 +1,293 @@ +--- +description: "Software Development Security Assessment" +sidebar_label: "Software Development at Obol" +slug: /advanced-and-troubleshooting/security/ev-assessment +--- + +# Software Development at Obol + +When hardening a project's technical security, team member's operational security, and the security of the software development practices in use by the team are some of the most critical areas to secure. Many hacks and compromises in the space to date have been a result of these attack vectors rather than exploits of the software itself. + +With this in mind, in January 2023 the Obol team retained the expertise of Ethereal Venture's security researcher Alex Wade; to interview key stakeholders and produce a report into the team's Software Development Lifecycle. + +The below page is a result of the report that was produced. What is present here has had some sensitive information redacted, and contains responses to the recommendations made, detailing the actions the Obol team have taken to mitigate what has been highlighted. + +## Obol Report + +**Prepared by: Alex Wade (Ethereal Ventures)** **Date: Jan 2023** + +Over the past month, I worked with Obol to review their software development practices in preparation for their upcoming security audits. My goals were to review and analyze: + +* Software development processes +* Vulnerability disclosure and escalation procedures +* Key personnel risk + +The information in this report was collected through a series of interviews with Obol’s project leads. + +## Contents + +* Background Info +* Analysis - Cluster Setup and DKG + * Key Risks + * Potential Attack Scenarios +* Recommendations + * R1: Users should deploy cluster contracts through a known on-chain entry point + * R2: Users should deposit to the beacon chain through a pool contract + * R3: Raise the barrier to entry to push an update to the Launchpad +* Additional Notes + * Vulnerability Disclosure + * Key Personnel Risk + +## Background Info + +**Each team lead was asked to describe Obol in terms of its goals, objectives, and key features.** + +### What is Obol? + +Obol builds DVT (Distributed Validator Technology) for Ethereum. + +### What is Obol’s goal? + +Obol’s goal is to solve a classic distributed systems problem: uptime. + +Rather than requiring Ethereum validators to stake on their own, Obol allows groups of operators to stake together. Using Obol, a single validator can be run cooperatively by multiple people across multiple machines. + +In theory, this architecture provides validators with some redundancy against common issues: server and power outages, client failures, and more. + +### What are Obol’s objectives? + +Obol’s business objective is to provide base-layer infrastructure to support a distributed validator ecosystem. As Obol provides base layer technology, other companies and projects will build on top of Obol. + +Obol’s business model is to eventually capture a portion of the revenue generated by validators that use Obol infrastructure. + +### What is Obol’s product? + +Obol’s product consists of three main components, each run by its own team: a webapp, a client, and smart contracts. + +* [DV Launchpad](../../learn/intro/launchpad.md): A webapp to create and manage distributed validators. +* [Charon](../../learn/charon/intro.md): A middleware client that enables operators to run distributed validators. +* [Solidity](../../learn/intro/obol-splits.md): Withdrawal and fee recipient contracts for use with distributed validators. + +## Analysis - Cluster Setup and DKG + +The Launchpad guides users through the process of creating a cluster, which defines important parameters like the validator’s fee recipient and withdrawal addresses, as well as the identities of the operators in the cluster. In order to ensure their cluster configuration is correct, users need to rely on a few different factors. + +**First, users need to trust the Charon client** to perform the DKG correctly, and validate things like: + +* Config file is well-formed and is using the expected version +* Signatures and ENRs from other operators are valid +* Cluster config hash is correct +* DKG succeeds in producing valid signatures +* Deposit data is well-formed and is correctly generated from the cluster config and DKG. + +However, Charon’s validation is limited to the digital: signature checks, cluster file syntax, etc. It does NOT help would-be operators determine whether the other operators listed in their cluster definition are the real people with whom they intend to start a DVT cluster. So - + +**Second, users need to come to social consensus with fellow operators.** While the cluster is being set up, it’s important that each operator is an active participant. Each member of the group must validate and confirm that: + +* the cluster file correctly reflects their address and node identity, and reflects the information they received from fellow operators +* the cluster parameters are expected – namely, the number of validators and signing threshold + +**Finally, users need to perform independent validation.** Each user should perform their own validation of the cluster definition: + +* Is my information correct? (address and ENR) +* Does the information I received from the group match the cluster definition? +* Is the ETH2 deposit data correct, and does it match the information in the cluster definition? +* Are the withdrawal and fee recipient addresses correct? + +These final steps are potentially the most difficult, and may require significant technical knowledge. + +## Key Risks + +### 1. Validation of Contract Deployment and Deposit Data Relies Heavily on Launchpad + +From my interviews, it seems that the user deploys both the withdrawal and fee recipient contracts through the Launchpad. + +What I’m picturing is that during the first parts of the cluster setup process, the user is prompted to sign one or more transactions deploying the withdrawal and fee recipient contracts to mainnet. The Launchpad apparently uses an npm package to deploy these contracts: `0xsplits/splits-sdk`, which I assume provides either JSON artifacts or a factory address on chain. The Launchpad then places the deployed contracts into the cluster config file, and the process moves on. + +If an attacker has published a malicious update to the Launchpad (or compromised an underlying dependency), the contracts deployed by the Launchpad may be malicious. The questions I’d like to pose are: + +* How does the group creator know the Launchpad deployed the correct contracts? +* How does the rest of the group know the creator deployed the contracts through the Launchpad? + +My understanding is that this ultimately comes down to the independent verification that each of the group’s members performs during and after the cluster’s setup phase. + +At its worst, this verification might consist solely of the cluster creator confirming to the others that, yes, those addresses match the contracts I deployed through the Launchpad. + +A more sophisticated user might verify that not only do the addresses match, but the deployed source code looks roughly correct. However, this step is far out of the realm of many would-be validators. To be really certain that the source code is correct would require auditor-level knowledge. + +The risk is that: + +* the deployed contracts are NOT the correctly-configured 0xsplits waterfall/fee splitter contracts +* most users are ill-equipped to make this determination themselves +* we don’t want to trust the Launchpad as the single source of truth + +In the worst case, the cluster may end up depositing with malicious withdrawal or fee recipient credentials. If unnoticed, this may net an attacker the entire withdrawal amount, once the cluster exits. + +Note that the same (or similar) risks apply to validation of deposit data, which has the potential to be similarly difficult. I’m a little fuzzy on which part of the Obol stack actually generates the deposit data / deposit transaction, so I can’t speak to this as much. However, I think the mitigation for both of these is roughly the same - read on! + +**Mitigation:** + +It’s certainly a good idea to make it harder to deploy malicious updates to the Launchpad, but this may not be entirely possible. A higher-yield strategy may be to educate and empower users to perform independent validation of the DVT setup process - without relying on information fed to them by Charon and the Launchpad. + +I’ve outlined some ideas for this in #R1 and #R2. + +### 2. Social Consensus, aka “Who sends the 32 ETH?” + +Depositing to the beacon chain requires a total of 32 ETH. Obol’s product allows multiple operators to act as a single validator together, which means would-be operators need to agree on how to fund the 32 ETH needed to initiate the deposit. + +It is my understanding that currently, this process comes down to trust and loose social consensus. Essentially, the group needs to decide who chips in what amount together, and then trust someone to take the 32 ETH and complete the deposit process correctly (without running away with the money). + +Granted, the initial launch of Obol will be open only to a small group of people as the kinks in the system get worked out - but in preparation for an eventual public release, the deposit process needs to be much simpler and far less reliant on trust. + +Mitigation: See #R2. + +**Potential Attack Scenarios** + +During the interview process, I learned that each of Obol’s core components has its own GitHub repo, and that each repo has roughly the same structure in terms of organization and security policies. For each repository: + +* There are two overall github organization administrators, and a number of people have administrative control over individual repositories. +* In order to merge PRs, the submitter needs: + * CI/CD checks to pass + * Review from one person (anyone at Obol) + +Of course, admin access also means the ability to change these settings - so repo admins could theoretically merge PRs without needing checks to pass, and without review/approval, organization admins can control the full GitHub organization. + +The following scenarios describe the impact an attack may have. + +**1. Publishing a malicious version of the Launchpad, or compromising an underlying dependency** + +* Reward: High +* Difficulty: Medium-Low + +As described in Key Risks, publishing a malicious version of the Launchpad has the potential to net the largest payout for an attacker. By tampering with the cluster’s deposit data or withdrawal/fee recipient contracts, an attacker stands to gain 32 ETH or more per compromised cluster. + +During the interviews, I learned that merging PRs to main in the Launchpad repo triggers an action that publishes to the site. Given that merges can be performed by an authorized Obol developer, this makes the developers prime targets for social engineering attacks. + +Additionally, the use of the `0xsplits/splits-sdk` NPM package to aid in contract deployment may represent a supply chain attack vector. It may be that this applies to other Launchpad dependencies as well. + +In any case, with a fairly large surface area and high potential reward, this scenario represents a credible risk to users during the cluster setup and DKG process. + +See #R1, #R2, and #R3 for some ideas to address this scenario. + +**2. Publishing a malicious version of Charon to new operators** + +* Reward: Medium +* Difficulty: High + +During the cluster setup process, Charon is responsible both for validating the cluster configuration produced by the Launchpad, as well as performing a DKG ceremony between a group’s operators. + +If new operators use a malicious version of Charon to perform this process, it may be possible to tamper with both of these responsibilities, or even get access to part or all of the underlying validator private key created during DKG. + +However, the difficulty of this type of attack seems quite high. An attacker would first need to carry out the same type of social engineering attack described in scenario 1 to publish and tag a new version of Charon. Crucially, users would also need to install the malicious version - unlike the Launchpad, an update here is not pushed directly to users. + +As long as Obol is clear and consistent with communication around releases and versioning, it seems unlikely that a user would both install a brand-new, unannounced release, and finish the cluster setup process before being warned about the attack. + +**3. Publishing a malicious version of Charon to existing validators** + +* Reward: Low +* Difficulty: High + +Once a distributed validator is up and running, much of the danger has passed. As a middleware client, Charon sits between a validator’s consensus and validator clients. As such, it shouldn’t have direct access to a validator’s withdrawal keys nor signing keys. + +If existing validators update to a malicious version of Charon, it’s likely the worst thing an attacker could theoretically do is slash the validator, however, assuming Charon has no access to any private keys, this would be predicated on one or more validator clients connected to Charon also failing to prevent the signing of a slashable message. In practice, a compromised Charon client is more likely to pose liveness risks than safety risks. + +This is not likely to be particularly motivating to potential attackers - and paired with the high difficulty described above, this scenario seems unlikely to cause significant issues. + +## Recommendations + +### R1: Users should deploy cluster contracts through a known on-chain entry point + +During setup, users should only sign one transaction via the Launchpad - to a contract located at an Obol-held ENS (e.g. `launchpad.obol.eth`). This contract should deploy everything needed for the cluster to operate, like the withdrawal and fee recipient contracts. It should also initialize them with the provided reward split configuration (and any other config needed). + +Rather than using an NPM library to supply a factory address or JSON artifacts, this has the benefit of being both: + +* **Harder to compromise:** as long as the user knows launchpad.obol.eth, it’s pretty difficult to trick them into deploying the wrong contracts. +* **Easier to validate** for non-technical users: the Obol contract can be queried for deployment information via etherscan. For example:\ + ![](/img/gitbook/image-50.png) + +Note that in order for this to be successful, Obol needs to provide detailed steps for users to perform manual validation of their cluster setups. Users should be able to treat this as a “checklist:” + +* Did I send a transaction to `launchpad.obol.eth`? +* Can I use the ENS name to locate and query the deployment manager contract on etherscan? +* If I input my address, does etherscan report the configuration I was expecting? + * withdrawal address matches + * fee recipient address matches + * reward split configuration matches + +As long as these steps are plastered all over the place (i.e. not just on the Launchpad) and Obol puts in effort to educate users about the process, this approach should allow users to validate cluster configurations themselves - regardless of Launchpad or NPM package compromise. + +**Obol’s response** + +Roadmapped: add the ability for the OWR factory to claim and transfer its reverse resolution ownership. + +### R2: Users should deposit to the beacon chain through a pool contract + +Once cluster setup and DKG is complete, a group of operators should deposit to the beacon chain by way of a pool contract. The pool contract should: + +* Accept Eth from any of the group’s operators +* Stop accepting Eth when the contract’s balance hits (32 ETH \* number of validators) +* Make it easy to pull the trigger and deposit to the beacon chain once the critical balance has been reached +* Offer all of the group’s operators a “bail” option at any point before the deposit is triggered + +Ideally, this contract is deployed during the setup process described in #R1, as another step toward allowing users to perform independent validation of the process. + +Rather than relying on social consensus, this should: + +* Allow operators to fund the validator without needing to trust any single party +* Make it harder to mess up the deposit or send funds to some malicious actor, as the pool contract should know what the beacon deposit contract address is + +**Obol’s response** + +Roadmapped: give the operators a streamlined, secure way to deposit Ether (ETH) to the beacon chain collectively, satisfying specific conditions: + +* Pooling from multiple operators. +* Ceasing to accept ETH once a critical balance is reached, defined by 32 ETH multiplied by the number of validators. +* Facilitating an immediate deposit to the beacon chain once the target balance is reached. +* Provide a 'bail-out' option for operators to withdraw their contribution before initiating the group's deposit to the beacon chain. + +### R3: Raise the barrier to entry to push an update to the Launchpad + +Currently, any repo admin can publish an update to the Launchpad unchecked. + +Given the risks and scenarios outlined above, consider amending this process so that the sole compromise of either admin is not sufficient to publish to the Launchpad site. It may be worthwhile to require both admins to approve publishing to the site. + +Along with simply adding additional prerequisites to publish an update to the Launchpad, ensure that both admins have enabled some level of multi-factor authentication on their GitHub accounts. + +**Obol’s response** + +We removed individual’s ability to merge changes without review, enforced MFA, signed commits, and employed Bulldozer bot to make sure a PR gets merged automatically when all checks pass. + +## Additional Notes + +### Vulnerability Disclosure + +During the interviews, I got some conflicting information when asking about Obol’s vulnerability disclosure process. + +Some interviewees directed me towards Obol’s security repo, which details security contacts: [ObolNetwork/obol-security](https://github.com/ObolNetwork/obol-security), while some answered that disclosure should happen primarily through Immunefi. While these may both be part of the correct answer, it seems that Obol’s disclosure process may not be as well-defined as it could be. Here are some notes: + +* I wasn’t able to find information about Obol on Immunefi. I also didn’t find any reference to a security contact or disclosure policy in Obol’s docs. +* When looking into the obol security repo, I noticed broken links in a few of the sections in README.md and SECURITY.md: + * Security policy + * More Information +* Some of the text and links in the Bug Bounty Program don’t seem to apply to Obol (see text referring to Vaults and Strategies). +* The Receiving Disclosures section does not include a public key with which submitters can encrypt vulnerability information. + +It’s my understanding that these items are probably lower priority due to Obol’s initial closed launch - but these should be squared away soon! \[Obol response to latest vuln disclosure process goes here] + +**Obol’s response** + +we addressed all of the concerns in the obol-security repository: + +1. The security policy link has been fixed +2. The Bug Bounty program received an overhaul and clearly states rewards, eligibility, and scope +3. We list two GPG public keys for which we accept encrypted vulnerabilities reports. + +We are actively working towards integrating Immunefi in our security pipeline. + +### Key Personnel Risk + +A final section on the specifics of key personnel risk faced by Obol has been redacted from the original report. Particular areas of control highlighted were github org ownership and domain name control. + +**Obol’s response** + +These risks have been mitigated by adding an extra admin to the github org, and by setting up a second DNS stack in case the primary one fails, along with general Opsec improvements. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/overview.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/overview.md new file mode 100644 index 0000000000..f7941f801b --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/overview.md @@ -0,0 +1,53 @@ +--- +description: "Security Overview" +sidebar_label: "Overview" +slug: /advanced-and-troubleshooting/security/overview +--- + +# Overview + +This page serves as an overview of the Obol Network from a security point of view. + +This page is updated quarterly. The last update was on 2025-December-05. + +View the operational status of Obol's supporting infrastructure at https://status.obol.org/. Your distributed validator does not require any centrally managed software to operate (if you run your own [relay](./risks.md)). + +## Table of Contents + +* [Overview](overview.md) + * [Table of Contents](overview.md#table-of-contents) + * [Official Domains and Channels](overview.md#domain-names-and-official-channels) + * [List of Security Audits and Assessments](overview.md#list-of-security-audits-and-assessments) + * [Security focused documents](overview.md#security-focused-documents) + * [Bug Bounty](overview.md#bug-bounty) + +## Domain names and official channels + +The Obol network and affiliated teams may use the following domain names and social media accounts; +- [obol.org](https://obol.org/) +- [obol.tech](https://obol.tech/) +- obol.dev +- [dvlabs.tech](https://dvlabs.tech/) +- [@obol_collective](https://twitter.com/obol_collective) on x.com +- [@dv_labs](https://x.com/dv_labs) on x.com + +Be wary of any communication presenting as related to Obol from other domains or social media accounts. Use good judgement and caution even when interacting with trusted domains and channels, as domain names, emails, and social media accounts can be compromised or impersonated. + +## List of Security Audits and Assessments + +The completed audits reports are linked [here](https://github.com/ObolNetwork/obol-security/tree/main/audits). + +* A review of Obol Labs [development processes](./ev-assessment.md) by [Ethereal Ventures](https://www.etherealventures.com/). +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/) resulting in version [`v0.16.0`](https://github.com/ObolNetwork/charon/releases/tag/v0.16.0). +* A second [assessment of Charon](https://obol.tech/charon_quantstamp_assessment.pdf) by [QuantStamp](https://quantstamp.com/) resulting in version [`v0.19.1`](https://github.com/ObolNetwork/charon/releases/tag/v0.19.1). +* A [solidity audit](./smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* A [penetration testing certificate](https://github.com/ObolNetwork/obol-security/blob/main/audits/Sayfer_2024-03_Penetration_Testing_CFD.pdf) of the Obol DV Launchpad by [Sayfer](https://sayfer.io/). +* A [second](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V2%20Audit%20-%20Nethermind.pdf) and [third](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V3%20Audit%20-%20Nethermind.pdf) solidity audit by [Nethermind Security](https://www.nethermind.io/nethermind-security). + +## Security focused documents + +* A [threat model](./threat_model.md) for a DV middleware client like Charon. + +## Bug Bounty + +Information related to disclosing bugs and vulnerabilities to Obol can be found on [the next page](bug-bounty.md). diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/risks.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/risks.md new file mode 100644 index 0000000000..384bdc26ef --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/risks.md @@ -0,0 +1,52 @@ +--- +description: "Outlining potential centralization risks and their mitigations" +sidebar_label: "Centralization Risks and Mitigation" +slug: /advanced-and-troubleshooting/security/risks +--- + +# Centralization Risks and Mitigation + +## Risk: Obol hosting the relay infrastructure + +**Mitigation**: Self-host a relay. + +One of the risks associated with Obol hosting the [LibP2P relays](../../learn/charon/charon-networking.md) infrastructure allowing peer discovery is that if Obol-hosted relays go down, peers won't be able to discover each other and perform the DKG or reconnect after a restart. To mitigate this risk, external organizations and node operators can consider self-hosting a relay. This way, if Obol's relays go down, the clusters can still operate through other relays in the network. Ensure that all nodes in the cluster use the same relays, or they will not be able to find each other if they are connected to different relays. + +The following non-Obol entities run relays that you can consider adding to your cluster (you can have more than one per cluster, see the `--p2p-relays` flag of [`charon run`](../../learn/charon/charon-cli-reference.md#the-run-command)): + +| Entity | Relay URL | +| ------------------------------------------- | ------------------------------------ | +| [DSRV](https://www.dsrvlabs.com/) | https://charon-relay.dsrvlabs.dev | +| [Infstones](https://infstones.com/) | https://obol-relay.infstones.com/ | +| [Hashquark](https://www.hashquark.io/) | https://relay-2.prod-relay.721.land/ | +| [Node Guardians](https://nodeguardians.io/) | https://obol-relay.nodeguardians.io/ | + +## Risk: Obol being able to update Charon code + +**Mitigation**: Pin specific docker versions or compile from source on a trusted commit. + +Another risk associated with Obol is the Labs team having the ability to update the [Charon code](https://github.com/ObolNetwork/charon) used by node operators within DV clusters, which could introduce vulnerabilities or malicious code. To mitigate this risk, operators can consider pinning specific versions or hashes of the Docker image or git repo commits that have been [thoroughly tested](overview.md#list-of-security-audits-and-assessments) and accepted by the network. This would ensure that any updates are carefully vetted and reviewed by the community, and only introduced into a running cluster gradually. The labs team will strive to communicate the security or operational impact any Charon update entails, giving operators the chance to decide whether they want potential performance or quality of experience improvements, or whether they remain on a trusted version for longer. + +## Risk: Obol hosting the DV Launchpad + +**Mitigation**: Use [`create cluster`](../../learn/charon/charon-cli-reference.md#the-create-command) or [`create dkg`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) locally and distribute the files manually. + +Hosting the first Charon frontend, the [DV Launchpad](../../learn/intro/launchpad.md), on a centralized server could create a single point of failure, as users would have to rely on Obol's server to access the protocol. This could limit the decentralization of the protocol and could make it vulnerable to attacks or downtime. Obol hosting the launchpad on a decentralized network, such as IPFS would be a first step but not enough. This is why the Charon code is source-available and contains a CLI interface to interact with the protocol locally. + +To mitigate the risk of launchpad failure, consider using the `create cluster` or `create dkg` commands locally and distributing the key shares files manually. + +## Risk: Obol custodying pre-signed exit messages + +**Mitigation**: Use withdrawal address initiated exits or validator client exits + +Before the Pectra hardfork, there was no way for a delegator to exit their validator without the co-operation of the node operator(s). In an effort to reduce this risk, Obol developed the [Charon exit](../../learn/charon/charon-cli-reference.md#the-exit-command) command, which allows operators to pre-sign and download exit messages to give to the delegator for safe keeping, ensuring they could broadcast them at any point in time. This feature relies on Obol's [API](../../api/what-is-this-api), and means the Obol core team could in theory initiate an unwanted exit. If a delegator does not want to be exposed to that centralization risk, they should not use Charon's built-in exit commands, and instead should initiate exits using the [EIP7002](https://eips.ethereum.org/EIPS/eip-7002) exit contract, or alternatively by running normal exit commands on the operator's validator clients. + +Guides to exiting validators using all three approaches are outlined [here](../../run-a-dv/running/exit-a-dv.mdx). + +## Risk: Obol going bust/rogue + +**Mitigation**: Use key recovery. + +The final centralization risk associated with Obol is the possibility of the company going bankrupt or acting maliciously, which could lead to a loss of confidence in the Charon client. To mitigate this risk, Obol has implemented a key reconstitution mechanism. This would allow the clusters to continue operating and to (re)create full validator private keys suitable for standard staking setups even if Obol is no longer able or willing to provide support. + +A guide to recombine key shares into a single private key can be accessed [here](../advanced/quickstart-combine.md). diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/smart-contract-audit.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/smart-contract-audit.md new file mode 100644 index 0000000000..a985f2f6a3 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/smart-contract-audit.md @@ -0,0 +1,491 @@ +--- +sidebar_label: "Smart Contract Audit" +slug: /advanced-and-troubleshooting/security/smart-contract-audit +--- + +# Smart Contract Audit + +The Obol Splits smart contracts have undergone multiple security audits to ensure the safety and reliability of the protocol. All audit reports are available in the [obol-splits audit directory](https://github.com/ObolNetwork/obol-splits/tree/main/audit). + +## Obol Splits V3 Audit (2025) + +Prepared by: Nethermind Security + +Date: 2025 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V3%20Audit%20-%20Nethermind.pdf) + +This audit covers the latest version of Obol Splits including the Obol Validator Manager (OVM) contracts and related improvements for Pectra upgrade support (EIP-7002 and EIP-7251). + +## Obol Splits V2 Audit (2025) + +Prepared by: Nethermind Security + +Date: 2025 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2025%20-%20Obol%20Splits%20V2%20Audit%20-%20Nethermind.pdf) + +This audit covers enhancements and updates to the Obol Splits protocol following the initial audit. + +## Obol Splits V1 Audit (2023) + +Prepared by: Zach Obront, Independent Security Researcher + +Date: Sept 18 to 22, 2023 + +[PDF Version](https://github.com/ObolNetwork/obol-splits/blob/main/audit/2023%20-%20Obol%20Splits%20V1%20Audit%20-%20Zach%20Obront.pdf) + +Markdown version of the audit follows below: + +### About **Obol** {#about-obol} +The Obol Network is an ecosystem for trust minimized staking that enables people to create, test, run & co-ordinate distributed validators. + +The Obol Manager contracts are responsible for distributing validator rewards and withdrawals among the validator and node operators involved in a distributed validator. + +### About **zachobront** {#about-zachobront} +Zach Obront is an independent smart contract security researcher. He serves as a Lead Senior Watson at Sherlock, a Security Researcher at Spearbit, and has identified multiple critical severity bugs in the wild, including in a Top 5 Protocol on Immunefi. You can say hi on Twitter at [@zachobront](http://twitter.com/zachobront). + +### Summary & Scope {#summary--scope} +The [ObolNetwork/obol-manager-contracts](https://github.com/ObolNetwork/obol-manager-contracts/) repository was audited at commit [50ce277919723c80b96f6353fa8d1f8facda6e0e](https://github.com/ObolNetwork/obol-manager-contracts/tree/50ce277919723c80b96f6353fa8d1f8facda6e0e). + +The following contracts were in scope: + +* src/controllers/ImmutableSplitController.sol +* src/controllers/ImmutableSplitControllerFactory.sol +* src/lido/LidoSplit.sol +* src/lido/LidoSplitFactory.sol +* src/owr/OptimisticWithdrawalReceiver.sol +* src/owr/OptimisticWithdrawalReceiverFactory.sol + +After completion of the fixes, the [2f4f059bfd145f5f05d794948c918d65d222c3a9](https://github.com/ObolNetwork/obol-manager-contracts/tree/2f4f059bfd145f5f05d794948c918d65d222c3a9) commit was reviewed. After this review, the updated Lido fee share system in [PR #96](https://github.com/ObolNetwork/obol-manager-contracts/pull/96/files) (at commit [fd244a05f964617707b0a40ebb11b523bbd683b8](https://github.com/ObolNetwork/obol-splits/pull/96/commits/fd244a05f964617707b0a40ebb11b523bbd683b8)) was reviewed. + +### Summary of Findings {#summary-of-findings} +| Identifier | Title | Severity | Fixed | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------- | ----- | +| [M-01](#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token) | Future fees may be skirted by setting a non-ETH reward token | Medium | ✓ | +| [M-02](#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) | Splits with 256 or more node operators will not be able to switch on fees | Medium | ✓ | +| [M-03](#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) | In a mass slashing event, node operators are incentivized to get slashed | Medium | | +| [L-01](#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) | Obol fees will be applied retroactively to all non-distributed funds in the Splitter | Low | ✓ | +| [L-02](#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) | If OWR is used with rebase tokens and there's a negative rebase, principal can be lost | Low | ✓ | +| [L-03](#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) | LidoSplit can receive ETH, which will be locked in contract | Low | ✓ | +| [L-04](#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) | Upgrade to latest version of Solady to fix LibClone bug | Low | ✓ | +| [G-01](#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) | stETH and wstETH addresses can be saved on implementation to save gas | Gas | ✓ | +| [G-02](#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) | OWR can be simplified and save gas by not tracking distributedFunds | Gas | ✓ | +| [I-01](#i-01-strong-trust-assumptions-between-validators-and-node-operators) | Strong trust assumptions between validators and node operators | Informational | | +| [I-02](#i-02-provide-node-operator-checklist-to-validate-setup) | Provide node operator checklist to validate setup | Informational | | + +### Detailed Findings {#detailed-findings} +#### \[M-01] Future fees may be skirted by setting a non-ETH reward token {#m-01-future-fees-may-be-skirted-by-setting-a-non-eth-reward-token} +Fees are planned to be implemented on the `rewardRecipient` splitter by updating to a new fee structure using the `ImmutableSplitController`. + +It is assumed that all rewards will flow through the splitter, because (a) all distributed rewards less than 16 ETH are sent to the `rewardRecipient`, and (b) even if a team waited for rewards to be greater than 16 ETH, rewards sent to the `principalRecipient` are capped at the `amountOfPrincipalStake`. + +This creates a fairly strong guarantee that reward funds will flow to the `rewardRecipient`. Even if a user were to set their `amountOfPrincipalStake` high enough that the `principalRecipient` could receive unlimited funds, the Obol team could call `distributeFunds()` when the balance got near 16 ETH to ensure fees were paid. + +However, if the user selects a non-ETH token, all ETH will be withdrawable only thorugh the `recoverFunds()` function. If they set up a split with their node operators as their `recoveryAddress`, all funds will be withdrawable via `recoverFunds()` without ever touching the `rewardRecipient` or paying a fee. + +**Recommendation** + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review** + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept** + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation** + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review** + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations** + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review** + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation** + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review** + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation** + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review** + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept** + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation** + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review** + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept** + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation** + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review** + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation** + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review** + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation** + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review** + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review** + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review** + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\ diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..1e557a58a5 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,155 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritise the liveness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalise operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator. A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..1ed84c4d89 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# troubleshooting + diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..7696b472b0 --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,298 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting any other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +For now, ENR rotation/replacement is not supported, it will be supported in a future release. Therefore, it's advised to always keep a backup of your `charon-enr-private-key ` in a secure location (ex: cloud storage, USB Flash drive, etc.). + +### I can't find the keys anywhere +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows. +Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + + +## Lighthouse + + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + + +### Lighthouse gives the error `not enough time for a discovery search` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance. +Using 3rd-party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Can't connect to Beacon API` + +If you are running EL and CL outside Obol on the same machine, you might need to open ports in your firewall to allow connections incoming from the docker instance. +In order to know the IP of the docker network, run: +`docker network inspect ` + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is +probably not online to sign successfully. Make sure all operators are +running the latest version of Charon. To check if some peers are not online: +`docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key +should be created and placed in the right directory during the ceremony. +Also, make sure you are working in the right directory: +`charon-distributed-validator-node`. + +### `Failed to confirm node connection` +Wait for Teku & Lighthouse sync to be complete. + + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum +limit has been reached. This is most often due to "maximum reservations per IP/peer". +This is when your Charon node is restarting or in some error loop and constantly +attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it. +This should allow the relay enough time to reset your IP/peer limits and +should then allow new reservations. This could also be due to the relay +being overloaded in general, so reaching a server wide "maximum connections" +limit. This is an issue with relay scalability and we are working in a long +term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO_RESERVATION (204)` indicates the peer +isn't connected to the relay, so the the Charon client cannot connect to the +peer via the relay. That might be because the peer is offline or the peer is +configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact +same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when +it failed to fetch the required data from the beacon node API. This indicates +a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +attestation data. This indicates the associated attestation duty failed to obtain +a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed due to no partial v2 committee subscription submitted by the cluster +validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation +duty failed in the fetcher component since it couldn't fetch the prerequisite +aggregated v2 committee subscription. This indicates the associated prepare aggregation +duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to insufficient +partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed due to no partial randao +signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed +in the fetcher component since it couldn't fetch the prerequisite aggregated +RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This +could indicate that insufficient honest peers participated in consensus or p2p +network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted +by the local validator client. This could indicate that the local validator client +is offline, or has connection problems with Charon, or has some other problem. +See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database +as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was +received from any peer. This indicates all peers are offline or p2p network connection +problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures +for the duty was received from peers. This indicates problems with peers or p2p +network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient +partial signatures failed. This indicates inconsistent signed data. This indicates +a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it +checks for a special file called the private key lock file. This file has the +same name as the ENR private key file but with a `.lock` extension. +If the private key lock file exists and is not older than 5 seconds, Charon won't +run. It doesn't allow running multiple Charon instances with the same ENR private +key. If the private key lock file has a timestamp older than 5 seconds, Charon +will replace it and continue with its work. If you`re sure that no other Charon +instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the +validators private key shares don't match the ENR private key. There may +have been a mix-up during deployment, leading to a mismatching validator +client key share index. + +For example: Imagine node N is Alice, and node M is Bob, the error would read: +` mismatching validator client key share index, Bob's key share submitted to Alice's charon node ` +Bob's private key share(s) are imported to a VC that is connected to +Alice's Charon node. This is an invalid setup/deployment. +Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside +cluster-lock.json and see that matches with the public key inside +`node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data the first time. +You can solve this by following the steps below: +- Click the Wheel Icon > Datasources. +- Click prometheus. +- Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +- Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel +Can be linked to a Teku keystore issue. + + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + You can ignore this error unless you have been contacted by the Obol Team + with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. + + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly +on Linux and WSL for Windows systems. In the interest of security, the +charon docker image runs as a non-root user, and this user often does not +have the permissions to write in the directory you have checked out the code +to. This can be generally be fixed with some of the following: +- Running docker commands with `sudo`, if you haven't [set up docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +- Changing the permissions of the `.charon` folder with the commands: + - `mkdir .charon` (if it doesn't already exist); + - `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + It`s because both Nethermind and Lighthouse start syncing and so there's + connectivity issues among the containers. Simply let the containers run for + a while. You won't observe frequent errors when Nethermind finishes syncing. You + can also add a second beacon node endpoint for something like Infura by + adding a comma separated API URL to the end of + `CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. + +### How do I fix the `plugin "loki" not found` error? + If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + + +## Relay + +### ` Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the +relay/docker-compose.yml with your real public IP or DNS hostname. + +### ` Timeout resolving bootnode ENR: context deadline exceeded` +The relay you are trying to connect to your peers via is offline or +unreachable. + diff --git a/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..83d3f55c5e --- /dev/null +++ b/versioned_docs/version-v1.8/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or uncontactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.8/api/address.mdx b/versioned_docs/version-v1.8/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.8/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.8/api/cluster-definition.mdx b/versioned_docs/version-v1.8/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.8/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.8/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.8/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..4da8ad1bcc --- /dev/null +++ b/versioned_docs/version-v1.8/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Effectiveness + + diff --git a/versioned_docs/version-v1.8/api/cluster-lock.mdx b/versioned_docs/version-v1.8/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.8/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.8/api/deposit-data.mdx b/versioned_docs/version-v1.8/api/deposit-data.mdx new file mode 100644 index 0000000000..a62f8c6aa7 --- /dev/null +++ b/versioned_docs/version-v1.8/api/deposit-data.mdx @@ -0,0 +1,18 @@ +--- +description: "Deposit Data related endpoints." +sidebar_label: "Deposit Data" +slug: /api/deposit-data +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Deposit Data + + + + + + + + + diff --git a/versioned_docs/version-v1.8/api/dv-exit.mdx b/versioned_docs/version-v1.8/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.8/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.8/api/dv-migrate.mdx b/versioned_docs/version-v1.8/api/dv-migrate.mdx new file mode 100644 index 0000000000..10073c62f5 --- /dev/null +++ b/versioned_docs/version-v1.8/api/dv-migrate.mdx @@ -0,0 +1,12 @@ +--- +description: "DV Migrate related endpoints." +sidebar_label: "DV Migrate" +slug: /api/dv-migrate +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Migrate + + + diff --git a/versioned_docs/version-v1.8/api/metrics.mdx b/versioned_docs/version-v1.8/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.8/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.8/api/owr-information.mdx b/versioned_docs/version-v1.8/api/owr-information.mdx new file mode 100644 index 0000000000..0e20b4892a --- /dev/null +++ b/versioned_docs/version-v1.8/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR + + diff --git a/versioned_docs/version-v1.8/api/state.mdx b/versioned_docs/version-v1.8/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.8/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.8/api/system.mdx b/versioned_docs/version-v1.8/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.8/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.8/api/techne-credentials.mdx b/versioned_docs/version-v1.8/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.8/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.8/api/terms-and-conditions.mdx b/versioned_docs/version-v1.8/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..d5d32a5dba --- /dev/null +++ b/versioned_docs/version-v1.8/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TermsAndConditions + + + + diff --git a/versioned_docs/version-v1.8/api/test.mdx b/versioned_docs/version-v1.8/api/test.mdx new file mode 100644 index 0000000000..841bedfb1c --- /dev/null +++ b/versioned_docs/version-v1.8/api/test.mdx @@ -0,0 +1,14 @@ +--- +description: "Test related endpoints." +sidebar_label: "Test" +slug: /api/test +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Test + + + + + diff --git a/versioned_docs/version-v1.8/api/tvs.mdx b/versioned_docs/version-v1.8/api/tvs.mdx new file mode 100644 index 0000000000..590b8a6c6b --- /dev/null +++ b/versioned_docs/version-v1.8/api/tvs.mdx @@ -0,0 +1,14 @@ +--- +description: "TVS (Total Value Staked) related endpoints." +sidebar_label: "TVS" +slug: /api/tvs +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TVS + + + + + diff --git a/versioned_docs/version-v1.8/api/what-is-this-api.md b/versioned_docs/version-v1.8/api/what-is-this-api.md new file mode 100644 index 0000000000..6951dbffbb --- /dev/null +++ b/versioned_docs/version-v1.8/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://launchpad.obol.org), a dApp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API can also be used via the [Obol-SDK](../sdk/index.md). + +Read more about Obol and how to use the [launchpad](https://launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.8/community-and-governance/community/README.md b/versioned_docs/version-v1.8/community-and-governance/community/README.md new file mode 100644 index 0000000000..c8d5f1c1b9 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# community + diff --git a/versioned_docs/version-v1.8/community-and-governance/community/grants-program/README.md b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/README.md new file mode 100644 index 0000000000..5d369cab6b --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/README.md @@ -0,0 +1,62 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/community/grants-program +--- + +# Grants Program + +We are excited to launch the **Obol Grants Program**. After a successful pilot wave that supported several meaningful initiatives, we’re doubling down on our commitment to ecosystem growth. + +If you're curious about what we funded in the past, check out our [Grants Pilot Wrap-Up blog post](https://blog.obol.org/grants-program-pilot-wave-report-pilot-phase-wrap-up/). It includes full context and direct links to our Questbook portal where you can browse the funded projects and on-chain disbursement records. + +*** + +## Purpose {#purpose} +The Obol Grants Program supports projects that advance the strategic goals of the Obol. The goal is to: + +* Provide milestone-based funding to **builders** aligned with our goals +* Offer a standardized and permissionless framework for **educators and event organizers** to run impactful Obol-focused community events & workshops +* Enable technical contributors to pick up **open-source missions** from our backlog + +This program exists to extend the reach of the Collective: helping us ship faster, strengthen adoption of Distributed Validators (DVs), other important Obol technology, and empower contributors globally. + +## Structure {#structure} +The Grants Program is organized into **three distinct Grant Tracks:** + +### [Staking Mastery Program](grants-track-for-staking-masters.md) {#staking-mastery-program} +* For contributors applying to work on any of the [Obol Collective 2025 SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388) +* This track revives the original Staking Mastery Program. I will now be running on a rolling basis to support research and technical contributions that advance distributed staking +* Open application process with milestone-based disbursement + +### [Community Events & Workshops](grants-track-for-community-events.md) {#community-events-and-workshops} +* For anyone hosting Obol-focused workshops, meetups or onboarding sessions +* Permissionless structure, funded retroactively based on proof of attendance and impact + +### [Open Strategic Missions](grants-track-for-open-strategic-missions/strategic-open-missions.md) {#open-strategic-missions} +* Pre-scoped, technical tasks created by Obol +* Contributors can apply to complete these missions for funding + +:::danger +Before applying, make sure to check the detailed sub-page for each grant track by clicking on its title above. These pages outline specific requirements, proof formats, and payout logic for each track. +::: + +## Review Timeline {#review-timeline} +All submitted applications (regardless of track) will receive an initial response within **7 business days**, with one of the following statuses: + +* ✅ **Accepted** — You’re good to start +* ❌ **Declined** — Not aligned with our current priorities +* 💬 **Needs Discussion** — We’d like to refine scope, budget, or timeline with you + +## Funding & Disbursement {#funding-and-disbursement} +* All grants are scoped and approved with a fixed amount in $OBOL, agreed upon upfront. +* Disbursements are made in **OBOL tokens**, disbursed upon approval of each milestone +* Payments can be **one-shot** or broken into **milestones**, depending on scope + +## Transparency & Communication {#transparency-and-communication} +* Every funded grant will be published publicly on **Questbook along with the detailed milestones and on-chain funding transactions.** You can find links to the relevant Questbook pages for each grant track in their dedicated sub-pages. +* Projects will be highlighted periodically through: +* Obol’s official social channels (Twitter, Discord) +* Grant recap blog posts & newsletters +* Grantees may be asked to publish short public recaps for visibility + +_**Ready to get started? You can learn more about each track by visiting the dedicated pages.**_ diff --git a/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-community-events.md b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-community-events.md new file mode 100644 index 0000000000..fd622dde5a --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-community-events.md @@ -0,0 +1,123 @@ +--- +sidebar_label: "Grants Track for Community Events" +slug: /community-and-governance/community/grants-program/grants-track-for-community-events +--- + +# Grants Track for Community Events + +This track supports permissionless, retroactive funding for Obol-focused local events, workshops, and onboarding sessions focused on Distributed Validators. + +The goal is to empower community leaders to grow Obol on the ground, with a clear and standardized support model. + +You can explore all supported events on [Questbook](https://questbook.app/dashboard/?grantId=68d793dd306fa3a0a64b83c2\&chainId=10). + +*** + +## Overview, Eligibility and Scope {#overview-eligibility-and-scope} +This track is designed to support **community-led educational events and workshops** that are **entirely focused on Obol Distributed Validators (DVs)**. These events should serve to onboard new participants, educate existing ones, and help expand the reach of Obol on the ground. + +To ensure consistency and predictability, this track uses a **permissionless framework** for supporting events with **up to 100 attendees.** Larger events may still be supported, but require prior coordination. + +Funding is available for two types of outcomes: + +1. **The event itself** — covering costs related to the event venue, food and beverages. +2. S**uccessful conversions to Obol DVs** — when attendees go on to spin up Distributed Validators using Obol technology, the event host or operators may qualify for a bonus reward. + +All events must: + +* Be **fully centered on Obol DVs** +* Be **submitted with the required proofs** to unlock retroactive funding upon verification +* Be limited to **100 participants or fewer** for automatic eligibility + +## Budget & Funding {#budget-and-funding} +### 🍕 1. Food & Drink Budget (Event Support) {#id-1.-food-and-drink-budget-event-support} +To help cover the costs of hosting, we provide **up to $15 per verified attendee**, retroactively, upon proof of the event. This amount includes the event venue, food, drinks, and minor operational expenses. + +* This support is **capped at 100 attendees per event.** +* Verification requirements are listed in the next section (“Submission Process”). + +### 🧪 2. TVS Conversion Bonus (Net New Stake Incentive) {#id-2.-tvs-conversion-bonus-net-new-stake-incentive} +To reward tangible ecosystem growth, we offer a **0.1% bonus of the total net new TVS (Total Value Staked)** attributable to your event. + +* Only **Obol-based DV clusters** are eligible. +* The **conversion must clearly follow from the event**, with proof submitted and verified. +* Bonus payouts will be made **monthly** over a **12-month period**, so long as the validators remain active. + +:::tip +For example, if your event led to the launch of 5 validators totaling 160 ETH (≈$640K TVS with ETH at $4000), you could be eligible for a $640 bonus, distributed over 12 months (\~$53.33/month), assuming validators remain online and performing. +::: + +This structure is designed to: + +* Ensure **sustainable staking growth**, not just one-time deposits +* Protect against potential **farming or gaming** of the bonus system +* Reward contributors for **long-term value creation** in the network + +:::danger +All budgets will be denominated in USD for clarity, and payments will be made in OBOL token equivalents at the time of disbursement. +::: + +:::tip +Want to estimate your potential TVS Conversion Bonus? Use this [simulator](https://bonus.gcp.obol.tech/) to adjust the ETH price and number of validators and preview your expected monthly rewards. +::: + +_The TVS conversion bonus will be paid directly to the operator who submits the form and verifies their validator address. It is then up to them to decide if or how they wish to share this bonus with the event organizer or other contributors. The Obol Association reserves the right to modify the bonus structure or reward calculation method at any time for future submissions. Any bonuses already approved and in-progress will remain unchanged and honored as agreed._ + +## Submission Process {#submission-process} +The Community Events track uses a simple **three-step submission flow**. Only one of them is optional, the rest are required for funding. + +### 1. [Pre-Event Form (optional but recommended)](https://forms.gle/Y5LTpEkF3TThRNUo9) {#id-1.-pre-event-form-optional-but-recommended} +We encourage hosts to fill out a short form **ahead of their event** to let the Association know what’s being planned. While not mandatory, this step allows us to: + +* Coordinate on visibility and cross-post the event on official channels +* Offer lightweight guidance or connections if needed +* Ensure the event fits within the scope of this grant track + +### 2. [Post-Event Submission (required for pizza & food budget)](https://forms.gle/MRZEaX3DtSZe9jSK7) {#id-2.-post-event-submission-required-for-pizza-and-food-budget} +After the event, hosts must fill out a **proof-of-event** form to unlock retroactive funding. This submission must include: + +* A **public tweet thread** summarizing the event ↳ Must highlight Obol DVs and mention @ObolCollective +* A **group photo** from the event, with clear timestamp and the organizer present +* Any **slides or presentation materials** used during the event +* A link to the **Luma page (or equivalent)** used for RSVPs ↳ Must include attendee list +* **Receipts** (food/beverage/venue) matching the number of participants + +_**Once submitted, your application will be reviewed and — if approved — disburse the food & drink budget (up to $15/attendee, max 100 attendees).**_ + +### 3. [TVS Conversion Bonus Submission (required for validator conversion bonus)](https://forms.gle/cmz5uw6cCwM5pZi96) {#id-3.-tvs-conversion-bonus-submission-required-for-validator-conversion-bonus} +There’s no deadline here, submit any time after the event once validators are live. To unlock your **TVS Conversion Bonus**, we require to fill the dedicated form with: + +* A submission from one of the **validator operators**, including: + * **Ethereum address** used to run the validator (to prove ownership) + * **Details of the Distributed Validator cluster** (to verify it was launched post-event) + * **Statement of correlation** explaining how the event led to this onboarding +* Follow-up confirmation from the **event organizer** +* A **public recap** from the host listing the validators or clusters onboarded via the event + +_**Once submitted, your application will be reviewed and — if approved — we will distribute the TVS bonus (0.1% of net new TVS distributed over 12 months).**_ + +## Evaluation & Review {#evaluation-and-review} +For **each of the three forms submitted** (pre-event intent, post-event proof, or TVS conversion bonus), Obol will respond within **seven open business days** with one of the following: + +* ✅ **Accepted** +* ❌ **Rejected** +* 💬 **Needs additional information** + +Once post-event materials have been reviewed and accepted, the host will be asked to **submit the final version of the application to Questbook**, including: + +* A summary of the event +* Final verified participant count +* Funding amount (e.g. food & drink budget) + +This Questbook submission will serve as the **source of truth for transparency and on-chain funding**. + +:::tip +If a validator conversion bonus is approved at a later date, it will be logged as a second milestone under the same Questbook grant and funded accordingly. +::: + +## Expectations & Visibility {#expectations-and-visibility} +We want to **showcase and amplify** meaningful contributions from the community. + +* If the event was flagged in advance via the optional pre-event form, we may help promote it via **Obol's official social media channels**, including social media and/or Discord. +* Once an event has been successfully validated and funded, it will be included in **periodic blog posts or funding recap threads.** +* We strongly encourage hosts to post their own event recaps publicly on X (Twitter) and **tag @ObolCollective** to boost visibility of their work and highlight the role of DVs in the broader staking ecosystem. diff --git a/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md new file mode 100644 index 0000000000..05db384572 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README.md @@ -0,0 +1,74 @@ +--- +sidebar_label: "Grants Track for Open Strategic Missions" +slug: /community-and-governance/community/grants-program/grants-track-for-open-strategic-missions +--- + +# Grants Track for Open Strategic Missions + +This track enables technical contributors to pick up pre-scoped missions designed by the Obol team. + +These missions are ideal for developers looking to ship meaningful tooling or infrastructure improvements for the DV ecosystem. + +To view active and completed missions, visit [Questbook](https://questbook.app/dashboard/?grantId=68d79449306fa3a0a64b88e9\&chainId=10). + +*** + +## Overview, Eligibility and Scope {#overview-eligibility-and-scope} +This track enables technical contributors to pick up **pre-scoped missions** designed by the Obol team. + +These missions are ideal for developers looking to ship meaningful tooling, research, or infrastructure improvements for **Obol Distributed Validators.** + +These missions are published directly in the [section below](strategic-open-missions.md). Each mission outlines: + +* The scope of work +* The deliverables expected +* The funding offered +* Context and materials + +This track is open to: + +* Independent developers and small technical teams +* Individuals with proven experience in Ethereum staking, especially Distributed Validators + +Our goal is to reduce internal backlog by collaborating with technically proficient external contributors who want to build meaningful tooling, integrations, or research for the Obol ecosystem. + +## Budget & Funding {#budget-and-funding} +Each mission comes with a proposed **budget offer.** These grants follow a **milestone-based payment** model: + +* Milestones are defined up front as part of the mission spec or during onboarding +* Funding is disbursed **only after milestone completion is validated** + +If adjustments are needed to the scope or funding, these will be clarified before the contributor starts work. + +## Submission Process {#submission-process} +Anyone interested in picking up a mission must fill out a [short application form](https://forms.gle/SgUx4n7hAZ28JpY47). It will request: + +* Name of the mission +* Background and relevant experience of the applicant(s) +* Relevant GitHub links or previous work +* Optional: Questions or additional clarification requests + +Only after submitting this form and receiving explicit approval may a contributor begin work. + +## Evaluation & Review {#evaluation-and-review} +Once an application form is submitted, Obol will provide a first response within **seven open business days**, which will be one of the following: + +1. ✅ **Accepted**: The contributor is cleared to begin work +2. ❌ **Rejected**: The contributor is not a fit or the mission is already taken +3. 💬 **Further discussion required**: Additional alignment on scope, timeline, or budget is needed + +:::danger +If you begin work without approval, we reserve the right to decline funding even if the work is completed. +::: + +## Expectations & Visibility {#expectations-and-visibility} +Contributors to this grant track will be expected to: + +* Provide milestone updates or completion summaries +* Be open to publishing public recaps or demos + +In return, Obol will: + +* Highlight completed missions on social channels +* Include them in quarterly reports and blog posts +* Provide visibility to help contributors build reputation diff --git a/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md new file mode 100644 index 0000000000..c25a9d1a9c --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions.md @@ -0,0 +1,77 @@ +--- +sidebar_label: "Strategic Open Missions" +slug: /community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions +--- + +# Strategic Open Missions + +To view ongoing and completed missions, visit [Questbook](https://questbook.app/dashboard/?grantId=68d79449306fa3a0a64b88e9\&chainId=10). + +This section will serve as the **central hub** for all currently available open missions under the Staking Mastery Program. + +* It will be updated regularly with new missions +* Completed missions will be archived +* Funded missions will be trackable via our Questbook hub + +Please check back soon for available missions. + +If you have a technical mission you'd like to propose to Obol instead, please use the [Staking Masters Grants track](../grants-track-for-staking-masters.md). + +*** + +## Open Strategic Missions {#open-strategic-missions} +This section lists specific, high-impact technical initiatives Obol has decided to open to external contributors. These are projects that contribute meaningfully to the Obol Distributed Validators (DVs) and we welcome applications from individuals or teams with the right expertise. + +Each mission includes a pre-defined scope and fixed budget. All applications are reviewed on a case-by-case basis. + +:::danger +All Open Missions must go through the official application and evaluation process before work begins. Milestone-based funding is tracked via Questbook and paid upon approval. +::: + +## 🟢 Open for Application {#open-for-application} +### Add Validator Feature in DappNode {#add-validator-feature-in-dappnode} +**Goal**: Implement the add-validator functionality into the Obol DappNode package, leveraging the existing docs as reference. + +🔗[Add Validators](../../../../advanced-and-troubleshooting/advanced/add-validators.md) + +**Background**: This feature would allow users to dynamically add validators post-launch via DappNode. It is not currently supported and would require someone familiar with the Obol DappNode integration layer. + +**Expected Deliverables:** + +* Integrate add-validator logic into DappNode package +* Ensure compatibility with Charon +* Include light documentation and testing instructions + +**Budget**: \~$1,000 USD + +**Funding**: Milestone-based, paid in $OBOL equivalent + +## 🟠 In Progress {#in-progress} +### TEEs for DVT Security (Sebastian Faust, PolyCrypt GmbH) {#tees-for-dvt-security-sebastian-faust-polycrypt-gmbh} +**Goal**: Prototype and benchmark how Trusted Execution Environments (Intel TDX) can secure DV operations. + +**Expected Deliverables:** + +* Run a DVT node (Charon + VC) inside Intel TDX +* Benchmark performance and risk mitigation +* Produce documentation, open-source code, and in-depth report + +**Funding**: $10,000 in stables + $10,000 in $OBOL + +**Status**: Started (September 2025) + +### Ansible Playbooks for Obol DVT (Jeremiah Sullivan) {#ansible-playbooks-for-obol-dvt-jeremiah-sullivan} +**Goal**: Build automated Ansible roles for DVT cluster deployment and home staking setups. + +**Scope**: + +* Docker Images with CI/CD for DVT components +* Ansible Roles for Charon deployment and validator configuration +* Monitoring setup with Grafana dashboards and webhook alerts +* Step-by-step documentation + +**Funding**: 7,000 $OBOL + +**Milestones**: Final delivery expected Q4 2025 + +**Status**: Ongoing (public GitHub in progress) diff --git a/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-staking-masters.md b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-staking-masters.md new file mode 100644 index 0000000000..19e62e9652 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/grants-program/grants-track-for-staking-masters.md @@ -0,0 +1,81 @@ +--- +sidebar_label: "Grants Track for Staking Masters" +slug: /community-and-governance/community/grants-program/grants-track-for-staking-masters +--- + +# Grants Track for Staking Masters + +This track covers proposals aligned with the [Collective’s SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388). + +It is designed for Staking Masters who want to proactively work on strategic initiatives that support Obol’s mission. + +You can browse funded grants and milestone details for this track on[ ](https://questbook.app/grants/obol/track-name-placeholder)[Questbook](https://questbook.app/dashboard/?grantId=68d792a86fd5365ca2538329\&chainId=10). + +*** + +## Overview, Eligibility and Scope {#overview-eligibility-and-scope} +The **Staking Mastery Program** is a rolling grant track designed to empower individual contributors and small technical teams working to advance distributed staking. This track revives the ethos of the original [Staking Mastery Cohorts](../staking-masters.md) by preserving their spirit of excellence, but adapts the structure to support proactive applications aligned with the [Obol Collective’s 2025 SQUAD Goals](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/388). + +Unlike the original cohort-based model, this new iteration operates on a rolling basis. Contributors can apply at any time to work on initiatives that push forward distributed validator adoption, improve technical general infrastructure, or deliver impactful research. The focus here is technical. One time education initiatives are supported separately through our [Community Events track](grants-track-for-community-events.md). + +This grant track is designed for proactive applications submitted by individual contributors or small teams interested in helping the Collective move forward. These can include topics such as: + +* Deepening DV penetration in staking and restaking protocols +* Expanding DV accessibility through tooling or automation +* Improving infrastructure compatibility with Obol DVs +* Conducting meaningful research in distributed validator technologies +* Integrating Defi protocols or adding more utility to the token + +**To be eligible, applications must:** + +* Be aligned with the 2025 SQUAD Goals of the Obol Collective +* Propose realistic deliverables that advance distributed staking +* Be led by individuals or small teams with proven technical expertise in staking, governance, infrastructure, or Ethereum protocols + +There is no fixed format or size constraint for proposals. We welcome both small- and large-scope projects but they should be concrete, measurable, and narratively clear. + +## Budget & Funding {#budget-and-funding} +Applicants must request funding using the template included in the application form. All budgets should be **denominated in $OBOL**, and payments will be made in **OBOL tokens**. + +Grants are **milestone-based**. This means: + +* Funding is **not disbursed upfront**. +* Each milestone must be **completed and approved** before the associated funding is released. +* Once a milestone is validated, the grantee can move on to the next phase and receive subsequent funding. + +## Submission Process {#submission-process} +There is no deadline or wave. Applications are accepted on a **rolling basis**. + +To apply, simply [fill out the dedicated application form](https://forms.gle/hJfXtGZFZqNoWAyE8), which includes sections for: + +* An overview of your project and its alignment with the Collective’s SQUAD Goals +* A breakdown of proposed milestones and deliverables +* Team background and relevant experience +* A detailed cost breakdown and requested budget (USD-denominated for the cost breakdown and converted into $OBOL for the budget request) + +## Evaluation & Review {#evaluation-and-review} +Once a submission is received, applicants can expect an **initial triage within 7 business days**. This first response will fall into one of three categories: + +1. ✅ **Accepted** — you’re good to move forward as-is. +2. ❌ **Rejected** — the proposal is not aligned or not feasible at this time. +3. 💬 **Discussion Required** — we’re interested, but need further alignment on scope, milestones, or budget. + +In most cases, we anticipate some **back-and-forth discussion** to refine the proposal before final approval. + +Once aligned, applicants will be asked to **submit the final version** of the grant to Questbook, including: + +* Project overview +* Final milestones +* Approved budget + +Questbook will serve as the **source of truth** for the proposal and allow anyone to **track the funding on-chain.** + +## Expectations & Visibility {#expectations-and-visibility} +We want to showcase the valuable work being built across the ecosystem. + +Upon completion of significant milestones (or the full project), we’ll highlight the grant publicly via: + +* Obol’s social channels +* Periodic blog posts or newsletters summarizing recent grants + +We also encourage grantees to share their own updates publicly, to **build visibility** for both their work and the broader Collective. diff --git a/versioned_docs/version-v1.8/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.8/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..e88964cd95 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/staking-masters.md @@ -0,0 +1,27 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program (Archived)" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\\ + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.8/community-and-governance/community/techne.md b/versioned_docs/version-v1.8/community-and-governance/community/techne.md new file mode 100644 index 0000000000..f7897a2455 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/community/techne.md @@ -0,0 +1,120 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\\ + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::info +For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. +::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.obol.org) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.obol.org) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.obol.org) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.8/community-and-governance/contribution/README.md b/versioned_docs/version-v1.8/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..5cff17667a --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# contribution + diff --git a/versioned_docs/version-v1.8/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.8/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +```markdown + ```javascript + console.log(error); + ``` +``` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.8/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.8/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e17d6226af --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +- Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +- Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/README.md b/versioned_docs/version-v1.8/community-and-governance/governance/README.md new file mode 100644 index 0000000000..55b1235949 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/README.md @@ -0,0 +1,58 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# Governance + +The Obol Collective is building a decentralized governance system rooted in the core values of Web3: transparency, openness, collaboration, and community-led decision making. At the same time, we recognize that decentralization is a journey, not a switch. Our aim is to progressively decentralize Obol governance in a way that is sustainable, resilient, and free of the common pitfalls that have emerged in the ecosystem. + +## Our Vision: Pragmatic Decentralization + +We are here to stay. And we believe the only way to build a resilient and successful decentralized collective is to start by building a strong foundation. In recent months, many leading DAOs have experienced operational bottlenecks, inefficiency, and growing pains from decentralizing too fast, too early. The result? Several are now walking back toward more centralized structures to regain coordination capacity, accountability, and operational agility. + +We’ve learned from these examples. Our approach is different: we are deliberately not rushing into maximal decentralization. Instead, we are laying the groundwork for progressive, sustainable decentralization over time. + +At this stage of the Collective, execution matters. Proposals are already going through governance processes, but the Obol Association still holds executional authority to move quickly where needed. We see this as a temporary and necessary condition to keep building and shipping. This balance, transparent governance with accountable execution, is critical to avoid decision paralysis. + +Governance at Obol is not about decentralization for its own sake. It is about enabling the best decisions for the long-term health of the network. As emphasized in the [Bell Curve governance roundtable](https://youtu.be/vF8XuRuZs9g?si=0dw3uh8gLXyvFlUH), decentralization without shared purpose or coordination leads to deadlock. We aim to build a governance model that supports rather than hinders progress. + +## Inspiration + +We draw inspiration from both the successes and challenges of other DAOs. In particular: + +* [**Arbitrum DAO**](https://forum.arbitrum.foundation/t/a-vision-for-the-future-of-arbitrum/28962), Introduced “Arbitrum Aligned Entities” to fix governance gridlock by assigning execution to focused teams, while keeping strategic control with the DAO. A response to over-decentralizing too quickly and losing operational clarity. +* [**Compound**](https://www.comp.xyz/t/proposal-to-create-the-compound-foundation/6777?utm_source=substack\&utm_medium=email), Proposed the Compound Foundation to help the DAO coordinate services, manage treasury execution, and maintain continuity — moving from pure DAO toward a hybrid model with accountable support. + +These initiatives reinforce our belief that progressive decentralization, aligned with clear domain ownership and accountable entities, leads to more sustainable governance. + +## Principles We Follow + +* **Decentralization is a means, not an end.** Governance exists to serve the network, not to complicate it. +* **Stakeholders should govern what they understand.** Validators and technical contributors guide protocol upgrades; token holders lead incentive and treasury decisions. +* **Social consensus is paramount.** On-chain votes matter, but upgrades only succeed through real-world coordination and adoption. +* **Structures must evolve with the protocol.** Governance at genesis won’t look like governance at maturity. We are building toward that future in deliberate steps. + +## Governance Tools + +To support transparent decision-making and empower active participation, here are key tools used across the Collective: + +* [**Governance Forum**](https://community.obol.org/) – for proposal discussion and coordination +* [**Voting Portal**](https://vote.obol.org/) – to delegate or vote on proposals +* [**Dune Dashboard**](https://dune.com/vistalabs/obol-governance) – to track voting data and delegate participation +* [**Staking Portal**](https://stake.obol.org/) – to stake OBOL and receive stOBOL +* [**0xretro.xyz**](https://0xretro.xyz/) – to access key info and metrics about delegates +* [**Curia Labs Dashboard**](https://obol.curiahub.xyz/delegate) – to find detailed insights on delegate reputation scores and contributions + +## Governance Sections + +The Obol governance documentation is organized into the following sections: + +* [collective.md](collective.md "mention") – framing the governance bodies, roles, and progressive decentralization pathway +* [token-house.md](token-house.md "mention") – the token-holder-based decision-making layer of the Collective +* [raf](raf/README.md "mention") – information for delegates participating in the Retroactive Funding Program (RAF) +* [grants-program](../community/grants-program/README.md "mention") – the Obol funding mechanism for contributors and ecosystem support, led by the Obol Association + +_These sections evolve as the governance process matures. For any feedback, ideas, or questions, we invite you to join the discussion on the_ [_Forum_](https://community.obol.org/) _or reach out via_ [_Discord_](https://discord.obol.org)_._ + +**Together, we are building governance for the long term.** diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/collective.md b/versioned_docs/version-v1.8/community-and-governance/governance/collective.md new file mode 100644 index 0000000000..4b93a757a8 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/collective.md @@ -0,0 +1,62 @@ +--- +description: "Obol Collective Overview" +sidebar_label: "Collective Overview" +slug: /community-and-governance/governance/collective +--- + +# Collective Overview + +## Purpose + +The Obol Collective’s governance system has two primary goals: + +1. **Resource allocation.** Allocate resources effectively to support the Collective’s vision and grow the Obol Collective's sustainable value. Long-term vision may sometimes conflict with short-term value creation; thus, governance requires a blend of short-term and long-term thinking to allocate the token treasury and protocol revenue effectively. +2. **Capture resistance.** Governance plays a key role in securing the anti-capture and censorship resistance of the Obol Collective. Governance should: + 1. make it possible for operations to continue over the long term without reliance on any individual entity; + 2. prevent any one entity or small group of entities from being able to control or censor. + +## Overview: The Obol Token House and RAF + +Two houses govern the Obol Collective: the Token House and the Obol RAF. + +In the **Token House,** OBOL Token holders are responsible for submitting, deliberating, and voting on governance proposals using the Governance Portal. Token holders can delegate their OBOL Token voting power to their own address or an eligible third party. Addresses with delegated voting power are called “Delegates”. + +In the **Obol Retroactive Fund (RAF)**, OBOL Token Delegates are responsible for allocating funds within the RAF to projects and teams that provide value to the Obol Collective. + +All OBOL holders and Delegates are expected to exercise their authority responsibly and follow the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. + +![](/img/gitbook/image-51.png) + +## The Security Council + +The Security Council is a committee of multi-sig wallet signers with the power to perform certain emergency actions as delegated to it by the Obol Association. + +The Security Council can execute any software upgrade or perform other emergency actions without delay to respond to a security emergency, should one arise. The Security Council must not use its power to perform Emergency Actions except in a true security emergency, such as a critical vulnerability that could significantly compromise the Obol Collective. + +After taking any Emergency Action, the Security Council must issue a full transparency report (at an appropriate time after the security emergency has passed) explaining what was done and why such action was justified. + +## Administration and Implementation + +In all cases, Obol Collective governance is intended to be carried out in a manner consistent with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. The Obol Association will steward this process as described below, with the goal of increasingly decentralising its role over time. + +The Obol Association, via its governance administrators, will facilitate administration to ensure that anyone may participate thoughtfully in governance. Such administrative services may include: + +* Moderation of governance proposals to ensure they are validly submitted and voted upon; +* Removal of proposals that reasonably appear to be fraudulent, spam-oriented, defamatory, hateful, or otherwise inappropriate or inconsistent with the values of the Collective; +* Monitoring of votes, voting power, the votable token supply, and voting periods for purposes of determining whether quorums and approval thresholds are met or accurately reflected; +* Management of mutually contradictory or duplicate proposals that are submitted simultaneously or close to one another; +* Maintenance of the Governance & RAF Portal; +* Other tasks that the Obol Association deems appropriate in connection with the above. + +The Association may also intervene operationally when necessary to uphold the integrity of the governance process — for instance, by removing improperly submitted proposals or enforcing community-agreed rules. When doing so, it will always act transparently and share justifications with the community. + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal or chosen RAF recipients, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails, coupled with an explanation. + +## Vision for Fully On-Chain Governance + +Once Collective’s governance develops and is deemed as sufficiently mature by the Obol Association, the implementations of passed proposals will follow full on-chain execution, where possible. Instead of the Collective’s reliance on the Obol Association for implementation, passed proposals will be moved to a queue to prepare for execution. The queue action will send the proposal to a Timelock contract, which starts a countdown until the proposal can be executed. + +Executing a proposal will run its function calls on-chain. Each proposal can be associated with one or more function calls. These calls will perform actions such as transferring assets from the treasury, updating the Governor's parameters, or calling another smart contract. diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/delegate-guide.md b/versioned_docs/version-v1.8/community-and-governance/governance/delegate-guide.md new file mode 100644 index 0000000000..5071ec9d15 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/delegate-guide.md @@ -0,0 +1,33 @@ +--- +description: "Delegate Guide" +sidebar_label: "Delegate Guide" +slug: /community-and-governance/governance/delegate-guide +--- + +# Delegate Guide + +## Delegate Rules of Engagement + +This document outlines the expectations, responsibilities, and values that should guide interactions within the Obol Collective governance community, including the Obol Forum, Discord, and working group meetings. This Code of Conduct will be reviewed periodically to incorporate feedback and adapt to governance needs. Any changes require community approval through the governance process. + +Please review these principles carefully to ensure alignment with the Obol Collective’s vision and commitment to a decentralized and sustainable ecosystem. + +Please read the rules of engagement on the forum [here](https://community.obol.org/t/delegates-rules-of-engagement/206). + +## **Governance Toolkit** + +These tools or their uses may change over time as governance evolves. For example, additional user interfaces dedicated to governance may be developed. Likewise, while voting currently takes place on-chain through the Governance Contract, some successful votes are administered and implemented by the Obol Association, which should not be the case indefinitely. + +Please see the toolkit on the forum [here](https://community.obol.org/t/governance-toolkit/207). + +## Delegates’ Role in the RAF + +The role of Delegates in the RAF is to allocate votes to projects that have made substantial positive impact on the Obol Collective’s Decentralized Operator Ecosystem. Vote allocation is proportional to the Delegates’ delegated power. To determine the funding amounts, the [quadratic funding](https://qf.gitcoin.co/) mechanism is used, to ensure a balanced and equitable distribution of influence. + +Visit read [the delegate guide](https://community.obol.org/t/delegate-guidelines-raf1/229) on the forum. + +## Delegate Compensation + +Starting August 2025, active delegates will be eligible for compensation based on their participation and contributions. This is determined using the **Delegate Reputation Score (DRS):** a scoring system that evaluates each delegate’s voting, rationale, and forum activity. Only delegates with a score of **65 or higher** will qualify for rewards. + +For full details on DRS and how compensation works, see the [Delegate Reputation Score & Compensation page.](delegate-guide/delegate-reputation-score-and-compensation.md) diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md b/versioned_docs/version-v1.8/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md new file mode 100644 index 0000000000..7874f36dc3 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation.md @@ -0,0 +1,101 @@ +--- +sidebar_label: "Delegate Reputation Score & Compensation" +slug: /community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation +--- + +# Delegate Reputation Score & Compensation + +## Delegate Reputation Score & Compensation + +As the Obol Collective moves toward more mature governance, we are introducing a new system to help improve delegate accountability and guide token holder decisions: the **Delegate Reputation Score (DRS)**. + +This mechanism is part of a broader initiative to evolve token governance beyond simple vote counts but toward systems that reward quality participation and reinforce long-term alignment. + +The Obol Collective is among the first DAOs to integrate this model, developed in collaboration with [Tally](https://www.tally.xyz/) and [Curia](https://obol.curiahub.xyz/delegate), helping to pioneer a new standard for **reputation-backed delegate governance**. + +## What is the Delegate Reputation Score (DRS)? {#what-is-the-delegate-reputation-score-drs} +The Delegate Reputation Score is a reputation system. It gives each delegate a score from 0 to 100 based on their behaviour across three core dimensions: + +* **Voting participation** +* **Forum rationale submissions** +* **Forum engagement (discussion and replies)** + +These inputs are tracked over a rolling window of proposals, with scoring updates happening after [every **governance cycle** (every 21 days)](https://app.gitbook.com/s/ym0xLVqLq5ZCK1Q02khi/community-and-governance/governance/token-house#token-house-governance-proposal-process). The current scoring logic can be found in full detail on [Curia’s documentation](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f), which also serves as the canonical source of truth. + +:::tip +**When does my DRS update?** + +Scores are updated every 21-day governance cycle, but with a 6-day delay after the submission window closes. + +This ensures all proposals, including those submitted just before the deadline, have completed their full voting period before scores are recalculated. This buffer guarantees consistency and fairness across the cycle. +::: + +Delegates can view their scores, and token holders can browse and filter delegates based on their reputation and activity levels directly on [Tally](https://www.tally.xyz/gov/obol/delegates). + +### Why it matters {#why-it-matters} +CommentThe DRS is designed to: + +* Help token holders delegate more effectively, with clearer visibility into how delegates are behaving +* Increase accountability by making governance activity measurable and comparable +* Reinforce quality and trust within the delegate set + +In practice, this means token holders are strongly encouraged, through the UI and incentive systems, to **delegate to high-DRS delegates**, while delegates are incentivized to maintain an active and transparent presence in the Collective’s governance. + +_**This is not just a dashboard feature. DRS has real consequences for rewards and visibility.**_ + +### Delegate Statuses by DRS + +Delegates can fall into different categories based on their Delegate Reputation Score (DRS), which is recalculated after every governance cycle. These statuses help token holders understand delegate behavior and make informed delegation decisions: + +* Active: Delegates with a DRS ≥ 65 are considered _active. T_his is the ideal status. Active delegates are eligible for compensation and prominently displayed in the UI to encourage token holders to delegate to them. + * Active (New): A delegate with a DRS ≥ 65 but who has participated in fewer than 5 proposals. While still considered active, this tag highlights that the delegate is relatively new, and their track record is limited. +* Inactive: Delegates with a DRS < 65. These delegates have either skipped votes or failed to post rationales, indicating lower governance engagement. + * Inactive (New): New delegates (fewer than 5 proposals) whose early participation has not met the DRS threshold. This tag signals limited history and insufficient engagement so far. +* Ghost: Delegates who have received voting power but have never participated in any governance vote. Once they vote on a proposal, they’ll transition into an active or inactive status depending on their initial DRS, and will also carry the “new delegate” tag until they surpass 5 evaluated proposals. + +### Bootstrapping New Delegates + +To avoid penalizing new contributors, DRS includes a bootstrapping mechanism. A delegate’s first vote will trigger their scoring process, and their initial DRS will be calculated based on that single proposal. Over time, the DRS evolves into a moving average across the last 5 proposals they were eligible to vote on. This ensures: + +* New delegates who actively participate from the start can achieve a high DRS immediately +* Inconsistent delegates see their score adjust quickly +* A consistent track record is required to maintain an active status + +Additionally, new delegates will be visibly tagged as such in the UI, signaling that their DRS is based on limited history. This helps token holders assess delegation options with full context and encourages early but consistent engagement. + +This design balances the need to reward early participation while preventing score manipulation. Active delegates (even if new) become eligible for compensation as soon as they meet the DRS threshold. + +## Delegate Compensation + +_Delegate Compensation is not live yet. It is scheduled to launch in the second part of August 2025._ + +We are also introducing **delegate compensations**, funded by the Delegate Rewards Pool. Compensation is **gated by DRS**: only delegates with a score of **65 or above** are considered “active” and eligible. + +Once classified as active, rewards are distributed using a **square root model**, based on delegated voting power. This model was selected to strike a balance between influence and fairness: + +* It reduces reward concentration among the largest delegates +* It supports smaller, high-performing delegates +* It helps foster a more pluralistic and sustainable governance ecosystem + +This approach is experimental and will be closely monitored. Over time, we may revisit weighting or distribution methods based on observed outcomes. + +### **Why Delegate Compensation?** + +At Obol, we believe that **no one should work for free. B**ut we also recognize that **not all participation is equally meaningful**. Delegate compensation isn’t about paying people to hold tokens or rubber-stamp votes. It’s about rewarding those who consistently engage with care, post structured rationales, and help the Collective navigate complex governance questions with thoughtfulness and integrity. + +Compensation is now earned through **visible, active contribution —** whether through dissent, alignment, or creative proposals — as long as it’s expressed in a way that moves the Collective forward. Good-faith disagreement and diversity of thought are part of what makes a governance system resilient. That’s the work we want to support. + +## A collaborative standard + +The DRS is a shared initiative between Obol, Tally (UI and standardization), and Curia (calculation and onchain oracle). While the Obol Collective is among the first to adopt this system, the hope is that it will be used by other DAOs seeking to upgrade their delegate models. + +We are proud to help drive this standard forward and will continue sharing learnings as we refine the system in practice. + +## Resources + +* [Tally Delegate Portal](https://www.tally.xyz/gov/obol/delegates) – see live DRS scores, search delegates, and explore participation history +* [Curia Dashboard](https://obol.curiahub.xyz/delegate) – DRS calculation details and complementary metrics +* [Curia's Source of truth for scoring logic](https://www.notion.so/DRS-v1-Implementation-Spec-Public-20f5e0b4886180219fcbfb8a2531264f) – Broken down calculation of DRS +* [OIP-4: Delegate Compensation & DRS Scoring](https://community.obol.org/t/oip-4-delegate-compensation-and-delegate-reputation-score-integration-for-stobol/522) – original governance proposal + +\\ diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/raf/README.md b/versioned_docs/version-v1.8/community-and-governance/governance/raf/README.md new file mode 100644 index 0000000000..44acaa1f05 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/raf/README.md @@ -0,0 +1,76 @@ +--- +description: "The RAF" +sidebar_label: "The RAF" +slug: /community-and-governance/governance/raf +--- + +# The RAF + +Obol’s Retroactive Funding (RAF) mechanism is designed to strengthen and promote the decentralisation of Ethereum's settlement layer by rewarding projects that add value and drive impact for Ethereum’s decentralisation. Read more about the Obol RAF [here](https://blog.obol.org/1-percent-for-decentralisation/). + +Voting and funding distributions occur over a series of **Obol Retroactive Fund (RAF)** rounds, with OBOL token Delegates determining how funds from the RAF are allocated. The first RAF round will open in February 2025. + +## Overview of the Obol RAF: + +* Any project that meets the RAF round’s criteria can make an application. +* OBOL Token Delegates vote on applications proportional to their delegated power and using [quadratic funding](https://qf.gitcoin.co/). +* The Obol RAF rounds occur at intervals and include phases for scoping, application creation, application review, voting, and funding distribution. +* The Obol Association will collect information from projects to distribute grants, including KYC, where required. + +Below is described the steps within each RAF round. Each step takes approximately one week.\\ + +![](/img/gitbook/image-53.png) + +### Step 1: Scoping + +The scope of the round’s impact and the amount of funding to be allocated is defined by the Obol Association at the outset of the round and posted on the Obol Forum. + +### Step 2: Application Registration + +Projects are invited to create an application on the [RAF App](http://raf.obol.org/). Any project or team can apply, but in the future, governance may decide that an application needs to be made by someone holding a minimum amount of OBOL tokens. + +Once a RAF round is opened, to apply for the Obol RAF, projects can create an application on [raf.obol.org](http://raf.obol.org/) by following these steps: + +1. **Create an Application:** Fill out the application form using the [RAF App](http://raf.obol.org/). +2. **Describe Impact:** Specify the category of the project and its impact. + +### Step 3: Application Review + +A subset of OBOL Delegates appointed by the Obol Association reviews applications to ensure compliance with the application rules. + +The Obol Association will also review applications to filter out spam or applications that do not align with the mission of the Obol Collective. + +### Step 4: Voting + +OBOL Delegates vote on projects in proportion to their voting power. Here’s how it works: + +1. **Eligibility:** Every address that has been delegated voting power by OBOL Token holders can submit votes. +2. **Voting Process:** Delegates vote using the [raf.obol.org](http://raf.obol.org) app. Depending on the type of application being reviewed, a specific set of criteria should be used to judge a project's contributions to the Obol Collective. + +:::warning +The Obol Association will monitor votes to ensure contributors are not voting for projects they are directly involved in or where a substantial conflict of interest may be present. Delegates are expected to act in accordance with the Delegate [Rules of Engagement](https://community.obol.org/t/delegates-rules-of-engagement/206) and the general [Code of Conduct](https://community.obol.org/t/code-of-conduct-for-discussion-forum/205) for the forum. +::: + +### Step 5: Tallying Results + +The voting power of each OBOL Token Delegate is proportional to the amount of OBOL tokens delegated to them. However, the funding results are calculated using [quadratic funding](https://qf.gitcoin.co/), meaning that the square root of the votes is used to determine the final allocation. This approach ensures a broader distribution of funding across the Obol Collective, rather than allowing a small number of winners to dominate. + +### Step 6: Compliance + +The Obol Association will review the list of selected projects, adjust if necessary and collect information from them to distribute the grant legally compliantly (including completing KYC if required). + +### Step 7: Funding distribution + +The overall reward amount for the round is divided among the winning projects based on the delegates' vote and allocation according to the quadratic funding mechanism. + +### **Step 8: Community retrospective** + +After each round, The Obol Association will conduct a retrospective and gather community feedback. + +## Guides for each Round + +RAF1: see the [RAF1 guide](https://community.obol.org/t/guide-for-raf-round-1-raf1/227) in the forum. + +## RAF1 Summary & Insights + +Head over to [raf1-guide.md](raf1-guide.md "mention") to find the results, top projects, and key takeaways from our first round. diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/raf/raf1-guide.md b/versioned_docs/version-v1.8/community-and-governance/governance/raf/raf1-guide.md new file mode 100644 index 0000000000..0acc913186 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/raf/raf1-guide.md @@ -0,0 +1,27 @@ +--- +sidebar_label: "RAF #1" +slug: /community-and-governance/governance/raf/raf1-guide +--- + +# RAF #1 + +## Learnings from RAF Round 1 + +Our first Retroactive Funding round (RAF1) awarded 1 million OBOL to 46 projects using a quadratic voting mechanism. Projects were evaluated on technical impact, contribution to decentralization, and public goods alignment. + +### Top-funded projects included: + +* Dappnode — integrated Obol into their Dappstore, enabling 16k+ validators to use Obol setups. +* Ethereum on ARM — ran distributed validators on low-cost devices. +* Stereum — offered one-click node deployment with Obol pre-installed, backed by strong GitHub and beaconcha.in adoption metrics. + +### Key learnings: + +* Impact evaluation is challenging without clear data; future rounds may require stronger entry thresholds. +* Quadratic voting worked to elevate broadly supported projects, but needed clearer onboarding. +* Delegates requested better UX for wallets and real-time visibility into vote progress. +* Community engagement was strong but limited in feedback volume — improving outreach will be a focus + +_**We’re using these insights to shape future RAF rounds, with an emphasis on transparency, fairness, and long-term ecosystem impact.**_ + +👉 [Read the full blog post here](https://blog.obol.org/raf1-results/) diff --git a/versioned_docs/version-v1.8/community-and-governance/governance/token-house.md b/versioned_docs/version-v1.8/community-and-governance/governance/token-house.md new file mode 100644 index 0000000000..25a60f8ed3 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/governance/token-house.md @@ -0,0 +1,121 @@ +--- +description: "The Token House" +sidebar_label: "The Token House" +slug: /community-and-governance/governance/token-house +--- + +# The Token House + +In the Token House, OBOL Token holders are responsible for submitting, deliberating, and voting on various Obol Collective governance proposals. + +## Overview of the Obol Token House + +* Proposals are reviewed and voted on in three-week cycles. + +:::info +You can subscribe to the public calendar [here](https://calendar.google.com/calendar/u/0?cid=Y183YzQ0ZmYwZjM5ODE4ZTcyODg2OTM2MmI4ZWEyMGNmMDdhMmZmMmZiMzMxYjE2MjMwYzg3ZjQxZGRiYjA4N2ViQGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20\&ref=blog.obol.org) so you always know where the current cycle stands. +::: + +* In the first week, anyone may draft a proposal of any type based on [this template](https://community.obol.org/t/proposal-template/208) and post it on the [Forum](https://community.obol.org/) with \[Draft] in the title. Delegates, Obol Collective members, and the general public can provide feedback on proposals in the forum, which should be incorporated into the proposal using the author’s best judgment. +* Once your proposal has been approved by four top-100 Delegates (by voting power), add a link to your proposal to the Voting Cycle Roundup forum thread by the last day of Week 2, and update the title from \[Draft] to \[Final]. The proposal then moves on to Week 3: Voting. +* If your proposal is passed, the Obol Association will facilitate its administration, including distributing approved OBOL Tokens grants. +* If your proposal fails, you can make a new proposal in the next cycle, specifying how you have incorporated significant changes from your first proposal.\\ + + ![](/img/gitbook/Token_house.png) + +## Token House Governance Proposal Process + +Anyone can submit a proposal to the Token House by using the Governance Portal. Proposals are accepted or rejected using a voting process. A proposal must be one of the valid proposal types listed below and follow the voting process described here. + +All governance proposals go through a 3-week cycle. Each “week” runs from Thursday at 7:00 pm GMT until Wednesday at 7:00 pm GMT. + +### Valid Proposal Types + +All governance proposals must fall within one of the following categories: + +* Ecosystem grants +* Protocol upgrades +* Token inflation adjustment +* Treasury allocations +* Work agreements +* Veto on the Obol RAF operations + +The different requirements for submission and approval of each Proposal Type are summarized below. If a specific template is not specified below, proposals should follow this standard proposal template. + +All Ecosystem grant applications are processed by the Association. + +Below are listed types of Token House Proposals. Each has a two-week review period plus one week voting window, with an approval threshold of 51%. + +| Proposal Type | Description | Submission Requirements | +| :-----------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------- | +| Ecosystem grants | The Obol Association’s treasury may be used to support development of the Collective and/or growth of the ecosystem via the proposal template. | Forum proposal + On-Chain Voting | +| Token inflation adjustment | Changes to the OBOL Token Contract or its supply. | Forum proposal + On-Chain Voting | +| Treasury Appropriations | The amount of OBOL Tokens the Obol Association may spend or distribute annually | Proposal initiated by the Association + On-Chain Voting | +| Work agreements | Formal arrangements between the Obol Association and contributors, teams, or organizations tasked with advancing specific initiatives or responsibilities within the ecosystem | Forum proposal + On-Chain Voting | +| Veto on the Obol RAF operations | The veto mechanism serves as a safeguard against decisions or actions within the RAF operations that are misaligned with the mission of decentralization, transparency, or the collective interests of the community. | Forum proposal + On-Chain Voting | +| Protocol upgrades | Scheduled changes to the on-chain smart contracts comprising the protocol or governance contracts. | Forum proposal + On-Chain Voting | +| SQUAD Goals | It reflects the aim of establishing shared, strategic, and community-driven objectives. Goals are set annually, with each cycle beginning in April. | Forum proposal + On-Chain Voting | + +### Weeks 1-2: Feedback and Review + +All proposal types should be posted to the [Obol Forum](https://community.obol.org/) for review. Proposal authors are expected to respond to feedback from Obol Collective members and Delegates. + +Proposals should be: + +* Submitted as a new discussion thread on the [Governance Forum](http://community.obol.tech/) in the appropriate Proposal Category. +* Marked with \[Draft] in the title. +* Formatted and contain information consistent with the [standard proposal template](https://community.obol.org/t/proposal-template/208). + +Before the end of Week 2, a governance administrator will create a Voting Cycle Roundup thread in the forum summarising all the proposals that meet the voting requirements for Week 3 Voting. + +For proposals to proceed to Week 3, four of the top 100 delegates by voting power must give explicit approval on the discussion thread. Delegates may signal approval by pasting the following comment on the proposal discussion thread: _”I am an Obol Delegate \[link to your delegate commitment in your Tally profile] with sufficient voting power, and I believe this proposal is ready to move to a vote."_ + +If a Delegate approves a proposal to move to a vote, it does not endorse that proposal. It simply signifies that they believe the proposal is ready to move to a vote. + +After receiving the required approvals, the author should update the proposal title from \[Draft] to \[Final] and add a link to their proposal in the Voting Cycle Roundup thread by the last day of Week 2 at 19:00 GMT. Authors should also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal’s progress. Proposal authors should include relevant links if feedback was gathered outside the Forum (e.g., on Discord). + +If a proposal author does not get explicit approval or wants more time for feedback, they should not include their proposal in the Voting Cycle Roundup thread. Instead, they should continue to seek community feedback and submit an updated proposal in the next voting cycle. + +:::warning +If a proposal that did not receive explicit approval through the steps above is submitted to the voting portal, the Obol Association reserves the right to cancel it onchain. While the Association is currently working to formalize this cancel authority within the Governor contract, this measure helps preserve governance integrity and ensures that only properly vetted proposals are voted on. +::: + +### Week 3: Publish a Proposal Onchain and Voting + +During Week 3, a wallet holding at least [30,000 OBOL in voting power](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c#readContract) must publish the proposal on the [Obol Governance Platform](https://www.tally.xyz/gov/obol).\ +After publication, there is a 24-hour voting delay, during which the proposal can be canceled if necessary. The voting delay is the amount of time between when a proposal is submitted and when it goes up for voting. The delay gives token holders time to delegate their voting power before the vote starts or buy more votes. Governor takes a snapshot of all the voting power at the start of voting. Read more [here](https://docs.tally.xyz/set-up-and-technical-documentation/deploying-daos/how-to-pick-governor-parameters#how-to-pick-the-voting-delay). + +:::warning +Important: Any proposal published on Tally must exactly match the version approved by top delegates on the forum—word for word. Adding new elements that were not explicitly approved is strictly forbidden. Additionally, proposal authors must keep the first post of the forum thread updated to reflect the latest version, so readers don’t have to search the comment section for changes. +::: + +\ +After the 24 hours, Delegates (including OBOL Token holders who have self-delegated) vote on proposals via the [Obol Governance Portal](https://vote.obol.org/). All proposals are included in voting if they were added to the Voting Cycle Roundup thread before the deadline and have the approval of four top-100 delegates. + +A governance proposal is **approved** if it satisfies two requirements: + +* **Quorum:** A minimum number of OBOL Token votes measured as _a % of the total votable OBOL Token supply, as of the start of the voting period._ “Votable supply” is the total amount of OBOL Tokens that have been delegated (including to oneself) and, therefore, can participate in voting. The current definition for the OBOL Token House is 0.84% of minted supply. +* **Approval threshold:** The minimum _% of votes cast in support relative to the total number of votes._ The current definition for the OBOL Token House is 0.01% of minted supply. + +A snapshot is taken at the start of each voting period to determine each delegate’s voting power. Voting is hosted on the Obol Governance Portal. + +If a proposal is submitted for a vote and does not pass, the proposal will not be executed. If a proposal author wishes to iterate on a rejected proposal, they should: + +1. Create a new proposal thread on the Forum. +2. Include a link to the first proposal that did not pass. +3. Clearly identify what has changed in the new proposal. + +:::warning +If the same proposal fails to pass two consecutive times (i.e., it is rejected onchain twice in a row), it may not be reintroduced or submitted again for a minimum period of 5 **governance cycles** — roughly equivalent to 3.5 **months** (based on the current 3-week cycle length). This ensures that only well-formed, broadly supported proposals proceed and discourages repeated cycling of the same topic without meaningful revision or support. +::: + +### Timelock Delay + +After the voting period ends, if the proposal passes, there will be a 5-day timelock delay. The timelock delay is the minimum time required between the approval and execution of a proposal. This delay gives stakeholders a final opportunity to review and react before the proposal is implemented. Read more [here](token-house.md#implementation). + +## Implementation + +Approved governance proposals will be routed to the Obol Association for implementation. Upon receipt of an approved proposal, the Obol Association will determine whether the proposal is safe, consistent with the purposes of the Obol Collective, and capable of being implemented legally (including potential KYC requirements). + +* If it is, the Association will act diligently and in a commercially reasonable manner to consider the proposal for implementation. +* If it is not, the Association may, at its discretion, remove the proposal for resubmission or implement it with guardrails. diff --git a/versioned_docs/version-v1.8/community-and-governance/obol-token/README.md b/versioned_docs/version-v1.8/community-and-governance/obol-token/README.md new file mode 100644 index 0000000000..2d56947810 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/obol-token/README.md @@ -0,0 +1,82 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/obol-token +--- + +# The OBOL Token + +The OBOL Token is central to the governance and operation of the Obol Collective. It serves multiple purposes that are essential to its functioning. + +**OBOL Token Transferability:** With the approval of[ OIP-2](https://community.obol.org/t/oip-2-unlock-obol-token/317/30), the OBOL Token is set for a strategic and well-planned unlock. The tokens will be unlocked on the 7th May 2025 at 11:00 UTC, following the completion of centralized exchange listings. Please go to [claim.obol.org](https://claim.obol.org) to unlock airdrop tokens. + +## Token Contract + +The official token contract address of the OBOL Token is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7) + +## Official Uniswap Pool + +The official Uniswap Pool for the OBOL Token is [https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434](https://app.uniswap.org/explore/pools/ethereum/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434) + +## Verified Contract Addresses {#verified-contract-addresses} +The following smart contracts power OBOL staking, governance, and reward distribution on Ethereum mainnet. + +
+ +Governor Contract + +* **Address:** [`0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c`](https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c) +* **Purpose:** Manages onchain proposal lifecycle and voting logic for Token House governance. +* **What you can find onchain:** + * Voting thresholds + * Quorum settings, + * Delay/period configs, + * Proposal and vote history. + +
+ +
+ +Auto Delegate (Overwhelming Support Strategy) + +* **Address:** [`0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158`](https://etherscan.io/address/0xCa28852B6Fc15EbD95b17c875D5Eb14b08579158) +* **Purpose:** Implements the “Overwhelming Support” auto-delegation strategy. This contract casts votes on behalf of un-delegated or transferred stOBOL when proposals receive strong community support. This mechanism uses tokens that would otherwise not be available in governance to ensure uncontroversial proposals will meet quorum. +* **What you can find onchain:** + * Parameters like `supportThreshold`, `subQuorumBips`, and `votingWindow` + * Proposals voted on by the strategy + * Vote power amounts cast + * Event logs showing execution activity + * Wallets or protocols interacting with auto-delegation logic + +
+ +
+ +Lockup / Unlock Contract (Airdrop Claim NFTs + +* **Contract name:** ObolLockups +* **Address:** [0x3b9122704a20946e9cb49b2a8616ccc0f0d61adb](https://etherscan.io/address/0x3b9122704a20946e9cb49b2a8616ccc0f0d61adb) +* **Network:** Ethereum mainnet +* **Purpose:** This contract was used during the OBOL airdrop to manage token lockups. Airdrop allocations were issued as **NFT-based lockups**, allowing recipients to claim their tokens and unlock them over time **without a fixed deadline**. The original claiming interface ([claim.obol.org](http://claim.obol.org)) is no longer live. However, the lockups remain fully accessible **onchain**, and users can still unlock their tokens directly via the contract. +* **How the mechanism works:** + * Each airdrop recipient received an NFT representing a locked OBOL allocation. + * The NFT encodes the lockup parameters. + * Tokens can be unlocked by calling the unlock function on the contract once the conditions are met. +* **What you can find onchain:** + * NFT ownership (ownerOf) + * Lockup parameters + * Locked and unlocked token balances + * The unlock function used to release available tokens + * Administrative parameters related to transferability and global lockups +* **Important note for users:** If you believe you still have locked OBOL tokens from the airdrop, you can: + * Verify that you hold an **ObolLockups NFT** at the address above. + * Interact **directly with this contract on Etherscan** to call the unlock function. + +For security reasons, users should **only** interact with the contract address listed here and not rely on token or NFT names alone. + +
+ +## Learn more about... + +[token-distribution-and-liquidity.md](token-distribution-and-liquidity.md) +[token-holders-faq.md](token-holders-faq.md) +[tge-faq.md](tge-faq.md) diff --git a/versioned_docs/version-v1.8/community-and-governance/obol-token/tge-faq.md b/versioned_docs/version-v1.8/community-and-governance/obol-token/tge-faq.md new file mode 100644 index 0000000000..d8501c1ef2 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/obol-token/tge-faq.md @@ -0,0 +1,140 @@ +--- +sidebar_label: "TGE FAQ" +slug: /community-and-governance/obol-token/tge-faq +--- + +# TGE FAQ + +## Unlock and Listing + +
+ +How do I unlock my OBOL Tokens received in the Airdrop? + +Starting May 7th at 11:00 AM UTC, visit [**claim.obol.org**](https://claim.obol.org), click **“Unlock”**, and follow the steps. + +
+ +
+ +When is the official TGE date and time? + +The OBOL Token will be listed on exchanges for deposit, trading and withdrawals on May 7th, 2025 at 11:00 AM UTC + +
+ +
+ +Where will the OBOL Token be listed for trading? + +* **Binance**, **Bybit**, **Bitget**, **Gate.io**, **MEXC**, and others. +* Check [CoinGecko](https://coingecko.com) or [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) for the most up-to-date list. + +
+ +
+ +What are the exact listing times on exchanges? + +* **Binance Alpha** – _May 7 at 10:00 AM UTC_ +* **Binance Futures** – _May 7 at 10:30 AM UTC_ +* **Bybit, Gate.io, Bitget, MEXC** – _May 7 at 11:00 AM UTC_ + +
+ +
+ +Where can I track the price of the OBOL Token? + +[CoinGecko](https://coingecko.com) and [CoinMarketCap](https://coinmarketcap.com/currencies/obol/) + +
+ +
+ +Where can I buy the OBOL Token onchain? + +* A **Uniswap v3 pool** will be seeded with initial liquidity. +* The contract address is [here](https://etherscan.io/address/0x57F52C9faa6D40c5163D76b8D7dD81ddB7c95434). +* Anyone can start a pool. Check live prices via **CoinGecko**, or **CoinMarketCap**. + +
+ +
+ +Are there any country restrictions for claiming or trading the OBOL Token? + +* Yes. Each venue has its own restrictions. +* Unlocking OBOL Tokens received through the Airdrop is subject to the same geo restrictions as claiming. + +
+ +## **Token Supply & Distribution** + +
+ +What is the circulating supply at TGE? + +Approximately 19**%**. Full breakdown is on [CoinMarketCap](https://coinmarketcap.com/currencies/obol/). + +
+ +
+ +Why does Etherscan show 374M tokens instead of 500M? + +For legal and tax reasons, not all tokens are minted yet. + +
+ +
+ +How many tokens were allocated to CoinList, and how many unlock at TGE? + +Details available on the [**Coinlist Sale Page**](https://coinlist.co/obol). + +
+ +
+ +When were unclaimed airdrop tokens returned to the treasury? + +As approved by [**OIP-2**](https://community.obol.org/t/oip-2-unlock-obol-token/317), they were [returned](https://etherscan.io/tx/0x738b4c252bb4613b9945e3b6426ec4ee510c6cdb86027fe20d533c4799a3a331) on **May 2, 2025**. + +
+ +## **Unlocks & Vesting** + +
+ +Can CoinList participants claim at TGE? + +Yes, a portion of their tokens will unlock on May 7th at 11AM UTC per the [**Coinlist terms**](https://coinlist.co/obol). + +
+ +
+ +Will RAF1 tokens be available at TGE? + +RAF1 tokens will be distributed **shortly after TGE**. + +
+ +
+ +When will OBOL Token incentives be claimable? + +Starting May 12, 2025 + +
+ +## **Token Utility** + +
+ +What is the utility of the OBOL Token? + +See the top of the page + +
diff --git a/versioned_docs/version-v1.8/community-and-governance/obol-token/token-distribution-and-liquidity.md b/versioned_docs/version-v1.8/community-and-governance/obol-token/token-distribution-and-liquidity.md new file mode 100644 index 0000000000..fad713567f --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/obol-token/token-distribution-and-liquidity.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Distribution & Liquidity" +slug: /community-and-governance/obol-token/token-distribution-and-liquidity +--- + +# Token Distribution & Liquidity + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](../governance/raf/README.md)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.8/community-and-governance/obol-token/token-holders-faq.md b/versioned_docs/version-v1.8/community-and-governance/obol-token/token-holders-faq.md new file mode 100644 index 0000000000..0888f499f9 --- /dev/null +++ b/versioned_docs/version-v1.8/community-and-governance/obol-token/token-holders-faq.md @@ -0,0 +1,77 @@ +--- +description: "This page is designed to answer the most common questions from OBOL token holders, particularly those holding liquid OBOL or stOBOL." +sidebar_label: "Token Holders FAQ" +slug: /community-and-governance/obol-token/token-holders-faq +--- + +# Token Holders FAQ + +## General + +
+ +What is the OBOL token used for? + +OBOL is the governance token of the Obol Collective. It enables holders to participate in on-chain governance by voting directly or delegating their voting power to delegates. + +OBOL is also used in the [RAF](../governance/raf/), where token holders delegate to vote on which contributors should receive retroactive funding for valuable work. + +In addition, OBOL can be staked to receive stOBOL, a liquid token that accrues staking rewards and retains governance power as long as it remains in the staker’s wallet. This staking mechanism supports long-term alignment and decentralized ownership. + +Finally, both OBOL and stOBOL are being integrated into DeFi protocols, such as liquidity pools, lending platforms (e.g. Morpho), and restaking services (e.g. Eigenlayer, Symbiotic), with more utility expected over time as shaped by community governance. + +
+ +
+ +Where can I see OBOL price, supply, and markets? + +You can track OBOL on [CoinMarketCap](https://www.coingecko.com/en/coins/obol-2) or [Coingecko](https://coingecko.com). These pages include market data, supply information, and live price charts. + +
+ +## Delegation & Governance + +
+ +How do I delegate my OBOL tokens? + +You can delegate via [vote.obol.org](https://vote.obol.org/dao/delegates). Connect your wallet, choose a delegate, and confirm the delegation transaction. + +
+ +
+ +Can I change my delegate? + +Yes, you can re-delegate at any time through the Collective Portal at [vote.obol.org](https://vote.obol.org) + +
+ +
+ +Does holding OBOL give me passive income? + +Not directly. Only staking OBOL (to receive auto-compounding stOBOL) allows you to earn rewards. + +
+ +## Token Value & Utility + +
+ +Does OBOL accrue fees? + +Currently, OBOL does not accrue protocol revenue. However, the DAO may vote in the future to direct protocol revenue toward token holders or stakers. + +
+ +
+ +How can I stay up to date on OBOL news? + +Join our [Discord](https://discord.obol.org), follow [@ObolNetwork](https://x.com/Obol_Collective), and check our [Forum](https://community.obol.org) for governance and integration updates. + +
+ +_This page is updated regularly. If your question isn’t listed, reach out via Discord or the Governance Forum._ diff --git a/versioned_docs/version-v1.8/learn/charon/README.md b/versioned_docs/version-v1.8/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.8/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.8/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.8/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..f3a277d2ec --- /dev/null +++ b/versioned_docs/version-v1.8/learn/charon/charon-cli-reference.md @@ -0,0 +1,1089 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.8.0`](https://github.com/ObolNetwork/charon/releases/tag/v1.8.0). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + deposit Sign and fetch a new partial deposit. + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. + --zipped Create a tar archive compressed with gzip of the cluster directory after creation. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost or pedersen. (default "default") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH+ staked for each). (default 1) + --operator-addresses strings Comma-separated list of each operator's Ethereum address. + --operator-enrs strings Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + --publish Creates an invitation to the DKG ceremony on the DV Launchpad. Terms and conditions apply. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 30s) + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 1m0s) + --zipped Create a tar archive compressed with gzip of the target directory after creation. +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --consensus-protocol string Preferred consensus protocol name for the node. Selected automatically when not specified. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + --graffiti strings Comma-separated list or single graffiti string to include in block proposals. List maps to validator's public key in cluster lock. Appends "OB" suffix to graffiti. Maximum 28 bytes per graffiti. + --graffiti-disable-client-append Disables appending "OB" suffix to graffiti. Increases maximum bytes per graffiti to 32. + -h, --help Help for run + --jaeger-address string [DISABLED] Listening address for jaeger tracing. + --jaeger-service string [DISABLED] Service name used for jaeger tracing. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --otlp-address string Listening address for OTLP gRPC tracing backend. + --otlp-headers strings Comma separated list of headers formatted as header=value, to include in OTLP requests. + --otlp-insecure Use insecure connection (no TLS) when connecting to OTLP endpoint. + --otlp-service-name string Service name used for OTLP gRPC tracing. (default "charon") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") + --vc-tls-cert-file string The path to the TLS certificate file used by charon for the validator client API endpoint. + --vc-tls-key-file string The path to the TLS private key file associated with the provided TLS certificate. +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its validator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + delete Delete a signed exit message from the remote API + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Delete exit message + +Delete a previously signed exit message for a given validator from the remote API. The required flag is either `--validator-public-key` of the validator message you wish to delete or `--all` to delete all validators' exit message. + +```markdown +charon exit delete --help +Deletes a partially signed exit message for a given validator from the remote API. + +Usage: + charon exit delete [flags] + +Flags: + --all Exit all currently active validators in the cluster. + -h, --help Help for delete + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### List active validators + +The `charon exit active-validator-list` command returns a list of all distributed validators in the specified cluster whose status is ACTIVE_ONGOING, meaning they can be exited. + +```markdown +charon exit active-validator-list --help +Returns a list of all the DVs in the specified cluster whose status is ACTIVE_ONGOING, i.e. can be exited. + +Usage: + charon exit active-validator-list [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for active-validator-list + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --plaintext Prints each active validator on a line, without any debugging or logging artifact. Useful for scripting. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +## The `enr` command + +The standalone `charon enr` command prints an Ethereum Node Record (ENR) from the client's charon-enr-private-key. This serves as a public key that identifies this client to its peers. + +```markdown +charon enr --help +Prints an Ethereum Node Record (ENR) from this client's charon-enr-private-key. This serves as a public key that identifies this client to its peers. + +Usage: + charon enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr + --verbose Prints the expanded form of ENR. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default "./") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## The `deposit` command + +:::warning +Activating a validator with an incorrect withdrawal address likely results in a loss of the funds. Take care when preparing alternative deposit data for a single validator client. +::: + +For unused, inactive validators in an existing cluster, you can prepare alternative deposit data for them, allowing you to use them as validators for a different withdrawal address than originally intended. + +See the [advanced guide](../../advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md) for more. + +```markdown +Sign and fetch new deposit messages for unactivated validators using a remote API, enabling the modification of a withdrawal address after creation but before activation. + +Usage: + charon deposit [command] + +Available Commands: + fetch Fetch a full deposit message. + sign Sign a new partial deposit message. + +Flags: + -h, --help Help for deposit + +Use "charon deposit [command] --help" for more information about a command. + +``` + +### Sign a deposit for an alternative withdrawal address + +A threshold of node operators must run `charon deposit sign` with matching parameters, to enable a new deposit data to be fetched with `charon deposit fetch`. + +```markdown +Signs new partial validator deposit messages using a remote API. + +Usage: + charon deposit sign [flags] + +Flags: + --deposit-amounts uints Comma separated list of partial deposit amounts (integers) in ETH. (default [32]) + -h, --help Help for sign + --lock-file string Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --private-key-file string Path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed deposit to the publish-address API. (default 5m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-keys strings [REQUIRED] List of validator public keys for which new deposits will be signed. + --withdrawal-addresses strings [REQUIRED] Withdrawal addresses for which the new deposits will be signed. Either a single address for all specified validator-public-keys or one address per key should be specified. +``` + +### Download a fully signed alternative deposit message + +`charon deposit fetch` outputs a file `.charon/deposit-data-.json` for use with the Ethereum deposit contract. + +```markdown +Fetch full validator deposit messages using a remote API. + +Usage: + charon deposit fetch [flags] + +Flags: + --deposit-data-dir string Path to the directory in which fetched deposit data will be stored. (default ".charon/deposit-data-") + -h, --help Help for fetch + --lock-file string Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --private-key-file string Path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed deposit to the publish-address API. (default 5m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-keys strings [REQUIRED] List of validator public keys for which new deposits will be signed. +``` + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Edit cluster configuration + +The `charon alpha edit` commands allow you to modify existing distributed validator cluster configurations. + +```markdown +charon alpha edit --help +Subcommands allow users to modify existing distributed validator cluster configurations, such as adding and removing operators. + +Usage: + charon alpha edit [command] + +Available Commands: + add-operators Add new operators to an existing distributed validator cluster + add-validators Add new validators to an existing distributed validator cluster + recreate-private-keys Create new private key shares to replace existing validator private key shares + remove-operators Remove operators from an existing distributed validator cluster + +Flags: + -h, --help Help for edit + +Use "charon alpha edit [command] --help" for more information about a command. +``` + +#### Add validators to a cluster + +The `charon alpha edit add-validators` command allows you to generate new validators and add them to an existing cluster. This process is very similar to the `charon dkg` ceremony, which requires all node operators to participate, because under the hood it runs the same DKG protocol with additional actions and verifications. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit add-validators --help +Generates and appends new validator keys to an existing distributed validator cluster. + +Usage: + charon alpha edit add-validators [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for add-validators + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --num-validators int The number of new validators to generate and add to the existing cluster. (default 1) + --output-dir string The destination folder for the new (combined) cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the command, should be increased if the command times out. (default 1m0s) + --unverified If charon has no access to the existing validator keys, this flag allows the addition to proceed, but skips hashing and signing the new cluster lock data. charon run must be started with --no-verify flag. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +#### Add operators to a cluster + +The `charon alpha edit add-operators` command adds new operators to an existing distributed validator cluster whilst keeping all validator public keys unchanged. All existing operators and new operators must participate in this ceremony. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit add-operators --help +Adds new operators to an existing distributed validator cluster, keeping validator public keys unchanged. + +Usage: + charon alpha edit add-operators [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for add-operators + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --new-operator-enrs strings Comma-separated list of the new operators to be added (Charon ENR addresses). + --no-verify Disables cluster definition and lock file verification. + --output-dir string The destination folder for the new cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +#### Remove operators from a cluster + +The `charon alpha edit remove-operators` command removes operators from an existing distributed validator cluster whilst leaving all validators intact. Remaining operators must participate in this ceremony. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit remove-operators --help +Removes operators from an existing distributed validator cluster, leaving all validators intact. + +Usage: + charon alpha edit remove-operators [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for remove-operators + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --new-threshold int Optional override of the new threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. All operators must use the same value. + --no-verify Disables cluster definition and lock file verification. + --operator-enrs-to-remove strings Comma-separated list of operators to be removed (Charon ENR addresses). + --output-dir string The destination folder for the new cluster data. Must be empty. Optional for removed operators. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --participating-operator-enrs strings Comma-separated list of operator ENRs participating in the ceremony. Required if --operator-enrs-to-remove specifies more operators to remove than the fault tolerance of the current cluster. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +#### Recreate private key shares + +The `charon alpha edit recreate-private-keys` command creates new private key shares to replace the existing validator private keys whilst retaining the same operator identities and validator public keys. All operators must participate in this ceremony. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit recreate-private-keys --help +Creates new private key shares to replace the existing validator private keys while retaining the same operator identities. + +Usage: + charon alpha edit recreate-private-keys [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for recreate-private-keys + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --output-dir string The destination folder for the new cluster artifacts. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --shutdown-delay duration Graceful shutdown delay. (default 1s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Subcommands provide test suites to evaluate a cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure PingLoad DirectConn Libp2pTCPPortOpen PingRelay PingMeasureRelay Version Synced PingLoad Simulate1 Simulate100 Simulate500 Simulate1000 PingMeasure PeerCount Simulate10 SimulateCustom Ping Ping PingMeasure PingLoad Ping PingMeasure CreateBlock DiskWriteSpeed DiskReadSpeed DiskReadIOPS TotalMemory InternetLatency InternetDownloadSpeed InternetUploadSpeed DiskWriteIOPS AvailableMemory] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Simulate1000 SimulateCustom Version PingLoad Simulate10 Simulate500 Ping PingMeasure Synced PeerCount Simulate1 Simulate100] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [InternetDownloadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadSpeed AvailableMemory TotalMemory InternetLatency InternetUploadSpeed DiskReadIOPS] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [PingMeasure CreateBlock Ping] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [PingMeasure PingLoad DirectConn Ping Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.8/learn/charon/charon-networking.md b/versioned_docs/version-v1.8/learn/charon/charon-networking.md new file mode 100644 index 0000000000..d6cf789792 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/charon/charon-networking.md @@ -0,0 +1,82 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](#internal-validator-stack) and the [_external p2p network_](#external-p2p-network). + +### Internal Validator Stack {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](charon-cli-reference.md): + +* `--p2p-tcp-address`: Address for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](cluster-configuration.md#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p's Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives. Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\\ + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URLs. diff --git a/versioned_docs/version-v1.8/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.8/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..35b677f482 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralised backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long-term decentralisation of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability to remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore a trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.8/learn/charon/dkg.md b/versioned_docs/version-v1.8/learn/charon/dkg.md new file mode 100644 index 0000000000..5f7acf9daa --- /dev/null +++ b/versioned_docs/version-v1.8/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENR's nonce and resign with the client's private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participant's old keys out of a distributed validator in favour of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.8/learn/charon/intro.md b/versioned_docs/version-v1.8/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.8/learn/further-reading/README.md b/versioned_docs/version-v1.8/learn/further-reading/README.md new file mode 100644 index 0000000000..6432497dd7 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/further-reading/README.md @@ -0,0 +1,6 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading diff --git a/versioned_docs/version-v1.8/learn/further-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.8/learn/further-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..45e6731817 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/further-reading/ethereum_and_dvt.md @@ -0,0 +1,55 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum_and_dvt +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +\&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.8/learn/further-reading/peer_score.md b/versioned_docs/version-v1.8/learn/further-reading/peer_score.md new file mode 100644 index 0000000000..e79156eb98 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/further-reading/peer_score.md @@ -0,0 +1,48 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer_score +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of a rated network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.8/learn/further-reading/resources.md b/versioned_docs/version-v1.8/learn/further-reading/resources.md new file mode 100644 index 0000000000..dbd5286202 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/further-reading/resources.md @@ -0,0 +1,59 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/further-reading/resources +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.8/learn/further-reading/testnet.md b/versioned_docs/version-v1.8/learn/further-reading/testnet.md new file mode 100644 index 0000000000..9e69963aa5 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/further-reading/testnet.md @@ -0,0 +1,190 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/further-reading/testnet +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.8/learn/intro/README.md b/versioned_docs/version-v1.8/learn/intro/README.md new file mode 100644 index 0000000000..86437ddd26 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/README.md @@ -0,0 +1,9 @@ +--- +title: "Introduction" +description: "Overview of the Obol Collective and Distributed Validator concepts" +sidebar_label: "README" +slug: /learn/intro/intro +unlisted: true +--- + +Welcome to the Introduction section. Here you’ll find an overview of Obol, staking incentives, key DV concepts, and more. diff --git a/versioned_docs/version-v1.8/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.8/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..2d4c15b1e6 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/readme/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General {#general} +#### Does Obol have a token? {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/obol-token/) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/token/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7). + +#### Where can I learn more about Distributed Validators? {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from? {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node? {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster? {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine? {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator? {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum number of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](key-concepts.md#distributed-validator-threshold). + +### Obol Splits {#obol-splits} +#### What are Obol Splits? {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in the future a number of other LSPs. + +#### Are Obol Splits non-custodial? {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split? {#can-i-change-the-percentages-in-a-split} +Generally, Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work? {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](obol-splits.md). + +#### Are Obol Splits open source? {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited? {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md). + +#### Are the Obol Splits contracts verified on Etherscan? {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts? {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits? {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](obol-splits.md#optimistic-withdrawal-recipient), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](../../advanced-and-troubleshooting/troubleshooting/errors.md). diff --git a/versioned_docs/version-v1.8/learn/intro/key-concepts.md b/versioned_docs/version-v1.8/learn/intro/key-concepts.md new file mode 100644 index 0000000000..15e8cfcc73 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/key-concepts.md @@ -0,0 +1,117 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/readme/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimising downtime in mission-critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specialises in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof-of-stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys which together operate as a threshold key for participating in proof-of-stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that need to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 3 | 2/3 | Minimum to tolerate one offline node | +| 4 | 3/4 | Minimum to tolerate one **malicious** node | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +:::warning +Running the same Charon node in two places is considered a malicious (or byzantine) act, you should **take extra care not to run duplicate instances of a particular Charon peer if it is running in a three node setup**, which only tolerates one offline node, not a malicious one. Read more [here](../charon/cluster-configuration#cluster-size-and-resilience). +::: + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.8/learn/intro/launchpad.md b/versioned_docs/version-v1.8/learn/intro/launchpad.md new file mode 100644 index 0000000000..69e4e40aab --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/launchpad.md @@ -0,0 +1,51 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/readme/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~** Staking Launchpad**](https://launchpad.ethereum.org/), a public good open-source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high-trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI-friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +| ---------------- | -------------------------------------- | +| Mainnet | https://launchpad.obol.org | +| Gnosis Chain | https://gnosischain.launchpad.obol.org | +| Hoodi | https://hoodi.launchpad.obol.org | +| Holesky | https://holesky.launchpad.obol.org | +| Sepolia | https://sepolia.launchpad.obol.org | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +> \[!TIP] If you created a cluster locally, and didn't use the `--publish` command at the time, you can manually publish it by running this command from the folder with the `cluster-lock.json` in it. +> +> `curl -X POST -H "Content-Type: application/json" -d @cluster-lock.json https://api.obol.tech/v1/lock` + +## Use the Explorer + +Clicking "explore" on the top-right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.8/learn/intro/obol-collective.md b/versioned_docs/version-v1.8/learn/intro/obol-collective.md new file mode 100644 index 0000000000..c609e4f980 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/readme/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +The Obol Collective is the largest Decentralised Operator Ecosystem. We provide the technology, opportunities, and community to scale decentralised infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also Byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../further-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](../../api/what-is-this-api.md), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol's [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx), Obol's Distributed Validator Pod. +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.8/learn/intro/obol-incentives.md b/versioned_docs/version-v1.8/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..c673eb4a77 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/obol-incentives.md @@ -0,0 +1,178 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/readme/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible shortly after the OBOL Token is unlocked (as per O[IP#2](https://community.obol.org/t/oip-2-unlock-obol-token/)) and starts trading. + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralisation](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at any time but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.obol.org](https://discord.obol.org). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | diff --git a/versioned_docs/version-v1.8/learn/intro/obol-splits.md b/versioned_docs/version-v1.8/learn/intro/obol-splits.md new file mode 100644 index 0000000000..9acc342f89 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/obol-splits.md @@ -0,0 +1,254 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/readme/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators and their surrounding ecosystem of decentralised infrastructure. These contracts include: + +* Validator Managers: Contracts used for a validator's withdrawal address, enabling ownership transfer, partial withdrawals, full exits, and operator rotation. +* Reward Splitting contracts: Contracts to split ether (and tokens) across multiple entities. Developed by [Splits.org](https://splits.org/) + +Key Design Principles the Obol Smart Contract suite include are: + +* That they are secure. All [released](https://github.com/ObolNetwork/obol-splits/releases/) Obol Splits products are [audited by high quality security teams](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments). +* They are not upgradeable. +* They are self-sovereign. Any permissioned actions, such as withdrawal, exit, or operator rotation, are controlled by the user, not an unaccountable set of third parties with the ability to upgrade your contract's behaviour. +* They do not require a token to function. +* They are oracle-free. (Unless you intend to leverage a [swapper](https://docs.splits.org/core/swapper)). +* They divide the reward ether from principal ether such that staking providers can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal and reward_. +* That rewards can be withdrawn in an ongoing manner without exiting the validator. (Some conditions apply). + +## Obol Validator Managers {#obol-validator-managers} +An Obol Validator Manager (OVM) is a smart contract which manages the deposit, withdrawal, exit, and public key rotation of one or more Ethereum validators. It is deployed as the withdrawal address for a validator and supports 0x01 and 0x02 validator types. + +### Creation + +You create a new Validator Manager contract using the [factory](obol-splits.md#ovm-factory-deployment) by calling the `ObolValidatorManagerFactory.createObolValidatorManager()` function, passing: + +* `owner` - The address that is the ultimate administrator of this Validator Manager deployment, it manages the assignment of roles for the contract, and **can call all privileged methods**. This address is best suited to being a multi-sig (such as a [SAFE](https://safe.global)) with a large number of signers, used only as a fallback, or it can be owned temporarily, fine-grained roles can be assigned to addresses, and then the [`renounceOwnership()`](https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol#L186) or [`transferOwnership()`](https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol#L174) methods can be called. +* `beneficiary` - This is the **address where the principal will be returned** to when validators exit or a withdrawal above the `principalThreshold` is made. This can be changed later by the `owner` or addresses with the `SET_BENEFICIARY_ROLE`. +* `rewardRecipient` - This is the **address where the accrued ether reward will be sent** when `distributeFunds()` is called. Usually it is a [Pull Split](https://docs.splits.org/core/split-v2#how-it-works) from [splits.org](https://splits.org). This can be changed later by the `owner` or addresses with the `SET_REWARD_ROLE`. +* `principalThreshold` - This is a configurable amount of Ether which dictates at what amount of value in the contract should we consider it to be principal being returned rather than reward accrued. The amount is immutable. A sensible default here is 16 ether (16000000000 gwei), the threshold used in Obol's earlier [Optimistic Withdrawal Recipients](obol-splits.md#optimistic-withdrawal-recipient). Further detail in the [FAQ](obol-splits.md#faq) section. + +### Roles + +Obol Validator Managers implement standard Role-Based Access Control. The OVM has the following roles that can be granted by the OVM owner, using the `grantRoles()` function. + +* `DEPOSIT_ROLE`: Permits an address to call the `deposit()` function. +* `CONSOLIDATION_ROLE`: Permits an address to initiate a consolidation between one or more source validators and a target validator, all managed by this contract. All source and target validators must be active with a balance greater than 32 ether. +* `WITHDRAWAL_ROLE`: Permits an address to trigger a partial withdrawal, or full exit of all validators managed by this contract using [EIP7002](https://eips.ethereum.org/EIPS/eip-7002). +* `SET_BENEFICIARY_ROLE`: Permits an address to change the recipient of the principal returned when validators exit, or a withdrawal above the principalThreshold is initiated. Also this permits an address to adjust the amount of principal stake being tracked by the contract. +* `SET_REWARD_ROLE`: Permits an address to change the recipient of the reward when `distributeFunds()` is called. +* `RECOVER_FUNDS_ROLE`: Permits an address to initiate `ERC20.transfer()` calls to arbitrary external addresses, with the intent to recover otherwise stuck tokens. + +### Deposit + +Every validator managed by an Obol Validator Manager must be deposited through the `deposit()` method. This method has the same signature as the official Ethereum deposit contract, but internally it accounts for the principal amount being deposited for the future calculation of returns of principal vs rewards. Only the `owner` address, or any address with the `DEPOSIT_ROLE` can call this method. + +:::info +If a deposit was done directly to the official Ethereum deposit contract, the OVM will not have recorded the principal amount. To fix this, consider using `setAmountOfPrincipalStake()` to update the total principal amount of stake. +::: + +### Partial Withdrawals & Full Exits + +Obol Validator Managers support [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) smart contract-based withdrawals. The `owner` address, or any address with the `WITHDRAWAL_ROLE` can call the `withdraw()` method to initiate a partial (or full) withdrawal of the balance of a validator managed by this contract. + +:::info +If you request to withdraw an amount that would leave a validator with less than a 32 ETH balance, only the amount that would leave the validator with 32 ETH will be withdrawn. +::: + +:::info +If you request to partially withdraw a validator's balance, the funds will be available in the OVM contract at the end of the exit queue. (Usually \~27 hours) + +However, if you withdraw the full balance of the validator, triggering its complete exit, the Ether will be available to the OVM contract once the validator is through the exit queue, **and** the skimming process has completed. (Average of \~5 days) This could add a number of days to the wait for validator funds, and full exiting at an optimal moment could significantly shorten the duration. +::: + +```solidity +function withdraw( + bytes[] calldata pubKeys, + uint64[] calldata amounts, + uint256 maxFeePerWithdrawal, + address excessFeeRecipient + ) external payable onlyOwnerOrRoles(WITHDRAWAL_ROLE) {} +``` + +```solidity title="Event" + /// Emitted when a withdrawal request is submitted for a validator + /// @param pubKey Validator public key + /// @param amount Withdrawal amount in gwei + /// @param fee Fee paid for the withdrawal + event WithdrawalRequested(bytes pubKey, uint64 indexed amount, uint256 indexed fee); +``` + +### Validator Consolidations + +Obol Validator Managers support [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) smart contract-based validator consolidations. This is an important feature for rotating the private keys for the validators managed by this contract. The rotation of private keys allows for the secure re-distribution of validation duties amongst new operators, without a significant period of inactivity in a normal exit and recreate flow. + +The `owner` address, or any address with the `CONSOLIDATION_ROLE` can call the `consolidate()` method, to initiate a consolidation between one or more source validators and a target validator, all managed by this contract. + +:::info +All source and target validators must be active with a balance greater than 32 ether for the consolidation to succeed. The target validator must be an 0x02 type validator, 0x01 type validators can become 0x02 type through a self-consolidation, where the public key is the `source` and `target`. +::: + +:::info +It is possible to permissionlessly consolidate a validator into (or out of) an OVM. This could result in the OVM's `amountOfPrincipalStake()` not accurately reflecting the true amount of stake on validators exiting to the OVM withdrawal address. This could result in more (or less) ether being treated as reward, and disbursed to the rewardRecipient address. The owner of the OVM or any address with the `SET_BENEFICIARY_ROLE` can update the amount of Ether treated as principal with the `setAmountOfPrincipalStake()` function. +::: + +```solidity + struct ConsolidationRequest { + bytes[] srcPubKeys; + bytes targetPubKey; + } + + function consolidate( + ConsolidationRequest[] calldata requests, + uint256 maxFeePerConsolidation, + address excessFeeRecipient + ) external payable onlyOwnerOrRoles(CONSOLIDATION_ROLE) {} +``` + +```solidity title="Event" + /// Emitted when a consolidation request is submitted + /// @param srcPubKey Source validator public key + /// @param targetPubKey Target validator public key + /// @param fee Fee paid for the consolidation + event ConsolidationRequested(bytes srcPubKey, bytes targetPubKey, uint256 indexed fee); +``` + +### Token Recovery + +The `owner` address, or any address with the `RECOVER_FUNDS_ROLE` can call the `recoverFunds()` method, to send an ERC20 token balance on the ObolValidatorManager contract to an arbitrary `recipient` address. + +:::warning +Be cautious when interacting with unknown ERC20 addresses, they may not behave as anticipated. +::: + +```solidity + /// Recover non-OVM tokens to a recipient + /// @param nonOVMToken Token to recover + /// @param recipient Address to receive recovered token + function recoverFunds(address nonOVMToken, address recipient) external onlyOwnerOrRoles(RECOVER_FUNDS_ROLE) {} +``` + +``` title="Event" + /// Emitted after tokens are recovered to a recipient + /// @param nonOVMToken Recovered token (cannot be ETH) + /// @param recipient Address receiving recovered token + /// @param amount Amount of recovered token + event RecoverNonOVMFunds(address indexed nonOVMToken, address indexed recipient, uint256 amount); +``` + +## Optimistic Withdrawal Recipient {#optimistic-withdrawal-recipient} +![](/img/gitbook/image-15-1-1.png) + +Optimistic Withdrawal Recipients (OWRs) **are the predecessor to Obol Validator Managers**. The primary addition with Validator Managers is the role-based control over validator withdrawals, exits and consolidations. + +Optimistic Withdrawal Recipients allow for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use a splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + +## Split Contracts {#split-contracts} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Validator Managers focus on the former, split contracts focus on the latter. They are best used in tandem. + +![Obol Validator Manager in Tandem with an Execution Layer Fee recipient splitter contract](/img/gitbook/ovm_splits_overview.png) + +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. We recommend using a [SAFE wallet](https://safe.global) to manage the Split. + +#### (Gnosis) SAFE wallet {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administer an editable split. The most well-known deployment of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + +## Deployments + +### Obol Validator Manager Factory Deployment {#ovm-factory-deployment} +The `ObolValidatorManager` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/ovm/ObolValidatorManagerFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x2c26B5A373294CaccBd3DE817D9B7C6aea7De584](https://etherscan.io/address/0x2c26B5A373294CaccBd3DE817D9B7C6aea7De584) | +| Hoodi | [0x5754C8665B7e7BF15E83fCdF6d9636684B782b12](https://hoodi.etherscan.io/address/0x5754C8665B7e7BF15E83fCdF6d9636684B782b12) | +| Sepolia | [0xF32F8B563d8369d40C45D5d667C2B26937F2A3d3](https://sepolia.etherscan.io/address/0xF32F8B563d8369d40C45D5d667C2B26937F2A3d3) | + +### Obol Lido Split Factory Deployment {#ols-factory-deployment} +The `ObolLidoSplit` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/lido/ObolLidoSplitFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | --------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | | +| Hoodi | [0xb633CD420aF83E8A5172e299104842b63dd97ab7](https://hoodi.etherscan.io/address/0xb633CD420aF83E8A5172e299104842b63dd97ab7) | +| Sepolia | | + +### OWR Factory Deployment {#owr-factory-deployment} +The `OptimisticWithdrawalRecipient` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | +| Hoodi | [0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7](https://hoodi.etherscan.io/address/0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7) | + +## FAQ + +### What are Obol Splits? + +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido with Obol Lido Splits, and Native Staking with Obol Validator Managers. + +### Are Obol Splits non-custodial? + +Yes. Unless you were to decide to [deploy an editable splitter contract](obol-splits.md#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. Obol Validator Managers have owners and Role-Based Access Control, but these are self-sovereign and up to the deployer to set and manage. There is no third party with access to or control of your validators unless you grant them such access. + +### Obol Validator Managers + +#### What happens if I deposit to an OVM managed validator directly with the Ethereum deposit contract instead of through the dedicated OVM.deposit() method? + +In this case, the OVM contract will not have recorded the deposit as principal to be returned, so when the validator exits, it will be sent to the reward address. Consider editing the reward address to pay 100% to the principal recipient, exiting the validator, claiming the 'rewards', and editing the reward split back to normal, before depositing through the OVM for **a new validator private key** that exits to the same OVM contract. + +#### What is the principal threshold for? + +Determining if Ether returned from a validator is principal deposited or rewards accrued is difficult. Rather than introducing an off-chain proof system, or trusted oracle, Obol Splits adopt an assumption that a mass slashing so severe that the principal returned is less than 16 eth is very rare, and the outcome that would happen in that case is the rewards would be sent to the reward rather than principal address, an accepted risk. This however does impact reward claiming on very large 0x02 validators. A validator could have earned 20 ether in rewards, and if a request for withdrawal of 20 ether is processed, it would be subtracted from principal and disbursed to the principal recipient, and upon a full exit, the remaining eth beyond the principal would be sent to the rewards address. To avoid this, entities with the `WITHDRAWAL_ROLE` should withdraw increments less than the `principalThreshold` if they want it treated as reward, and more than `principalThreshold` if they want to process it as a direct exit. + +### Can I change the percentages in a split? + +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +### Are Obol Splits open source? + +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +### Are Obol Splits audited? + +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments) and always deploy contracts only from published [releases](https://github.com/ObolNetwork/obol-splits/releases). + +### Are the Obol Splits contracts verified on Etherscan? + +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +### Does my cold wallet have to call the Obol Splits contracts? + +No. Any address can trigger the contracts to distribute the withdrawn/skimmed ether, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +### Are there any edge cases I should be aware of when using Obol Splits? + +The most important thing to be aware of is what address is the owner of the Obol Validator Manager, whether it has assigned any other addresses any roles, and whether or not the Split contract you are using has been set up with editability and by which address. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is to use a high threshold multi-sign like a SAFE as the `owner`/`controller`, or to renounce ownership and control entirely, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](obol-splits.md#optimistic-withdrawal-recipient), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. diff --git a/versioned_docs/version-v1.8/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.8/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..becb3a6d90 --- /dev/null +++ b/versioned_docs/version-v1.8/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/readme/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and PKI + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.8/obol-stack/README.md b/versioned_docs/version-v1.8/obol-stack/README.md new file mode 100644 index 0000000000..43e436d665 --- /dev/null +++ b/versioned_docs/version-v1.8/obol-stack/README.md @@ -0,0 +1,110 @@ +--- +description: "A local Kubernetes-based framework for running blockchain networks" +sidebar_label: "Introduction" +slug: /obol-stack/obol-stack +--- + +# Introduction to the Obol Stack + +The Obol Stack is a local development environment for running blockchain networks on your machine. It provides a simplified CLI experience for managing a Kubernetes cluster with dynamically deployable network instances, allowing developers and operators to run Ethereum nodes, Layer 2 networks, and other blockchain infrastructure locally. + +:::info +The Obol Stack is designed for local development and testing. For production deployments, refer to the respective network documentation and use appropriate infrastructure. +::: + +## What is the Obol Stack? + +Obol Stack is a two-part system: + +1. **obolup.sh** - A bootstrap installer that sets up your environment +2. **obol CLI** - A Go-based binary for stack and network management + +The stack runs entirely on your local machine using [k3d](https://k3d.io/) (Kubernetes in Docker), providing a lightweight yet fully-featured Kubernetes environment for blockchain development. + +## Key features + +* **Local-first architecture** - Run everything on your machine without cloud dependencies. +* **Multiple network support** - Deploy Ethereum nodes, Helios light clients, Aztec sequencers, and more. +* **Unique deployments** - Each network installation creates a uniquely-namespaced deployment, allowing multiple instances of the same network type to run simultaneously. +* **Simplified tooling** - Wraps kubectl, helm, and other Kubernetes tools with automatic configuration. +* **Persistent storage** - Data persists across cluster restarts. + +## Core concepts + +### Stack lifecycle + +The Obol Stack follows a simple lifecycle: + +| Command | Description | +| --- | --- | +| `obol stack init` | Initialize cluster configuration | +| `obol stack up` | Start the Kubernetes cluster | +| `obol stack down` | Stop the cluster (preserves data) | +| `obol stack purge` | Remove cluster and configuration | + +### Network deployments + +Networks are deployed as isolated Kubernetes namespaces. Each deployment gets a unique identifier (either user-specified or auto-generated), enabling: + +* Multiple deployments of the same network type (e.g., mainnet and testnet Ethereum nodes) +* Isolated resources per deployment +* Independent lifecycle management +* Simple cleanup via namespace deletion + +### Passthrough commands + +Obol Stack wraps common Kubernetes tools with automatic kubeconfig configuration: + +```shell +obol kubectl get pods -A # kubectl with stack kubeconfig +obol helm list -A # helm with stack kubeconfig +obol k9s # k9s terminal UI +``` + +## System requirements + +### Prerequisites + +* **Docker** 20.10.0 or later (daemon must be running) +* **macOS** (Darwin) or **Linux** +* **amd64** or **arm64** architecture + +### Resource recommendations + +| Component | Minimum | Recommended | +| --- | --- | --- | +| **CPU** | 4 cores | 8 cores | +| **RAM** | 8 GB | 16 GB | +| **Storage** | 50 GB | 500+ GB (varies by network) | + +:::warning +Running full Ethereum nodes requires significant disk space. Mainnet execution clients can require 1+ TB of storage. Plan your storage accordingly based on which networks you intend to run. +::: + +## Architecture overview + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Obol Stack │ +├─────────────────────────────────────────────────────────────┤ +│ obol CLI │ +│ ├── stack (init, up, down, purge) │ +│ ├── network (list, install, sync, delete) │ +│ └── passthrough (kubectl, helm, helmfile, k9s) │ +├─────────────────────────────────────────────────────────────┤ +│ k3d Cluster │ +│ ├── 1 Server + 3 Agent Nodes │ +│ ├── Traefik Ingress (ports 8080, 8443) │ +│ └── Local Path Storage │ +├─────────────────────────────────────────────────────────────┤ +│ Network Deployments │ +│ ├── ethereum-mainnet-prod (namespace) │ +│ ├── ethereum-hoodi-test (namespace) │ +│ ├── aztec-mainnet-node (namespace) │ +│ └── helios-knowing-wahoo (namespace) │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Need assistance? + +If you have questions or encounter issues with Obol Stack, head over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.8/obol-stack/faq.md b/versioned_docs/version-v1.8/obol-stack/faq.md new file mode 100644 index 0000000000..a645fd1489 --- /dev/null +++ b/versioned_docs/version-v1.8/obol-stack/faq.md @@ -0,0 +1,295 @@ +--- +description: "Frequently asked questions about Obol Stack" +sidebar_label: "FAQ" +slug: /obol-stack/faq +--- + +# Frequently Asked Questions + +## General + +### What is Obol Stack? + +The Obol Stack is a local Kubernetes-based development environment for running blockchain networks. It uses k3d (Kubernetes in Docker) to provide a lightweight cluster where you can deploy Ethereum nodes, Layer 2 networks, and other blockchain infrastructure. + +### Is Obol Stack suitable for production? + +No. Obol Stack is designed for local development, testing, and experimentation. For production deployments, use dedicated infrastructure with proper security, redundancy, and monitoring. Refer to the specific network documentation for production deployment guidance. + +### What operating systems are supported? + +Obol Stack supports: + +* **macOS** (Darwin) - Intel and Apple Silicon +* **Linux** - amd64 and arm64 architectures + +Windows is not currently supported. Windows users can use WSL2 (Windows Subsystem for Linux) to run the Obol Stack. + +### What are the hardware requirements? + +Minimum requirements: + +| Resource | Requirement | +| --- | --- | +| **CPU** | 4 cores | +| **RAM** | 8 GB | +| **Storage** | 50 GB | + +Recommended for running full nodes: + +| Resource | Requirement | +| --- | --- | +| **CPU** | 8+ cores | +| **RAM** | 16+ GB | +| **Storage** | 500 GB - 2 TB (depends on network) | + +:::info +Running multiple networks or full Ethereum mainnet nodes significantly increases resource requirements. +::: + +## Installation + +### The installer fails with "Docker daemon not running" + +Ensure Docker is installed and running: + +```shell +# Check Docker status +docker info + +# Start Docker (macOS) +open -a Docker + +# Start Docker (Linux) +sudo systemctl start docker +``` + +### How do I update the Obol Stack? + +Re-run the installer to update to the latest version: + +```shell +bash <(curl -s https://stack.obol.org) +``` + +The installer will update the CLI binary while preserving your configuration and data. + +### How do I uninstall Obol Stack? + +1. Stop and remove the cluster: + +```shell +obol stack purge -f +``` + +2. Remove installed files: + +```shell +rm -rf ~/.config/obol +rm -rf ~/.local/share/obol +rm ~/.local/bin/obol +``` + +3. Optionally remove installed dependencies (kubectl, helm, k3d, etc.) from `~/.local/bin/`. + +### The installer cannot modify /etc/hosts + +The installer requires sudo access to add `obol.stack` to `/etc/hosts`. If this fails: + +1. Run the installer and skip the hosts configuration. +2. Manually add the entry: + +```shell +echo "127.0.0.1 obol.stack" | sudo tee -a /etc/hosts +``` + +## Stack operations + +### The cluster fails to start + +Common causes and solutions: + +**Docker resources insufficient:** + +Increase Docker's resource allocation in Docker Desktop settings (CPU, Memory, Disk). + +**Port conflicts:** + +Obol Stack uses ports 8080 and 8443. Check for conflicts: + +```shell +lsof -i :8080 +lsof -i :8443 +``` + +Stop any conflicting services before starting the stack. + +**Previous cluster not cleaned up:** + +```shell +# Force remove any existing cluster +k3d cluster delete --all +obol stack init --force +obol stack up +``` + +### How do I access the Kubernetes dashboard? + +Use k9s for a terminal-based dashboard: + +```shell +obol k9s +``` + +Or use kubectl directly: + +```shell +obol kubectl get all -A +``` + +### Can I use my existing kubectl configuration? + +Obol Stack uses an isolated kubeconfig file at `~/.config/obol/kubeconfig.yaml`. This prevents conflicts with your existing Kubernetes configuration. + +To use the Obol Stack's cluster with standard kubectl: + +```shell +export KUBECONFIG=~/.config/obol/kubeconfig.yaml +kubectl get nodes +``` + +### How do I persist data across cluster restarts? + +Data is automatically persisted. When you run `obol stack down`, the cluster stops but data remains in `~/.local/share/obol/`. Running `obol stack up` restores the cluster with all previous data. + +Only `obol stack purge -f` deletes persistent data. + +## Networks + +### How do I know which deployment ID was generated? + +The deployment ID is displayed when you run `obol network install`: + +``` +Generated deployment ID: knowing-wahoo +``` + +You can also list your deployments: + +```shell +ls ~/.config/obol/networks/ +``` + +### Can I run multiple instances of the same network? + +Yes. Each deployment gets a unique namespace. For example: + +```shell +obol network install ethereum --id=mainnet --network=mainnet +obol network install ethereum --id=hoodi --network=hoodi +``` + +This creates two separate deployments: `ethereum-mainnet` and `ethereum-hoodi`. + +### How long does it take to sync an Ethereum node? + +Sync times vary significantly: + +| Network | Execution Client | Approximate Time | +| --- | --- | --- | +| Hoodi | Reth | 2-6 hours | +| Hoodi | Geth | 4-12 hours | +| Mainnet | Reth | 1-3 days | +| Mainnet | Geth | 3-7 days | + +:::info +Sync times depend on your hardware, network connection, and current chain state. Consensus clients with checkpoint sync typically sync in minutes. +::: + +### My network deployment is stuck in Pending state + +Check for resource issues: + +```shell +# Check pod status +obol kubectl describe pod -n + +# Check events +obol kubectl get events -n + +# Check persistent volume claims +obol kubectl get pvc -n +``` + +Common causes: + +* **Insufficient resources** - Increase Docker's allocated resources. +* **PVC not bound** - Storage provisioner issue; try restarting the stack. +* **Image pull errors** - Network connectivity or rate limiting. + +### How do I view logs for my network? + +```shell +# View all pods in namespace +obol kubectl get pods -n - + +# Stream logs from a specific pod +obol kubectl logs -n - -f + +# View logs from all pods with a label +obol kubectl logs -n - -l app=execution -f +``` + +## Troubleshooting + +### Error: "stack not running, use 'obol stack up' first" + +The cluster is not running. Start it with: + +```shell +obol stack up +``` + +If the cluster was previously initialized, this will restore it. If not, run `obol stack init` first. + +### Error: "deployment not found" + +The specified network deployment does not exist. Check your deployment ID: + +```shell +# List installed networks +ls ~/.config/obol/networks/ + +# Use the correct format +obol network sync ethereum/correct-id +``` + +### Grafana shows "No data" + +Ensure Prometheus is running and scraping metrics: + +```shell +# Check Prometheus pods +obol kubectl get pods -n monitoring + +# Check ServiceMonitors +obol kubectl get servicemonitors -A +``` + +Networks must have the `release: monitoring` label to be discovered by Prometheus. + +### How do I report a bug? + +Report issues on GitHub: [https://github.com/ObolNetwork/obol-stack/issues](https://github.com/ObolNetwork/obol-stack/issues) + +Include: + +* Obol Stack version (`obol version`) +* Operating system and architecture +* Docker version (`docker version`) +* Steps to reproduce +* Relevant logs + +## Need more help? + +If your question is not answered here, head over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.8/obol-stack/installing-apps.md b/versioned_docs/version-v1.8/obol-stack/installing-apps.md new file mode 100644 index 0000000000..831feafa53 --- /dev/null +++ b/versioned_docs/version-v1.8/obol-stack/installing-apps.md @@ -0,0 +1,93 @@ +--- +description: "Deploy additional applications on your Obol Stack" +sidebar_label: "Installing Apps" +slug: /obol-stack/installing-apps +--- + +# Installing apps + +The Obol Stack supports installing additional applications on top of your local Kubernetes cluster. Applications extend the functionality of your stack with monitoring, RPC proxies, and other services. + +:::info +The application system is under active development. Currently, default applications are deployed automatically with the stack. The `obol app` command for installing additional applications is planned for a future release. +::: + +## Default applications + +When you run `obol stack up`, the following applications are automatically deployed: + +### Monitoring stack + +A complete monitoring solution based on Prometheus and Grafana: + +* **Grafana** - Dashboards and visualization +* **Prometheus** - Metrics collection and storage +* **Pre-configured dashboards** - Kubernetes and application metrics + +Access Grafana at: `http://grafana.localhost:8080` + +:::tip +Grafana is configured with anonymous admin access for local development. No login required. +::: + +Access Prometheus at: `http://prometheus.localhost:8080` + +### Local path provisioner + +Provides persistent storage for applications using local disk. All networks and applications use this storage class by default. + +## Application architecture + +Applications in Obol Stack follow a self-registration pattern for monitoring: + +* **ServiceMonitors** - Applications expose metrics that Prometheus discovers via the `release: monitoring` label. +* **Grafana dashboards** - Applications can provide dashboards via ConfigMaps with the `grafana_dashboard: "1"` label. + +This means networks you install (Ethereum, Aztec, etc.) automatically appear in the monitoring stack. + +## Planned features + +The following features are planned for future releases: + +### Application management commands + +```shell +obol app list # List available apps +obol app install # Install an application +obol app edit # Edit application configuration +obol app sync # Deploy/update application +obol app delete # Remove application +``` + +### Additional applications + +* **ERPC** - Unified RPC proxy and load balancer for Ethereum endpoints +* **Obol Frontend** - Web-based management interface + +## Viewing application status + +Check running applications: + +```shell +# View default namespace resources +obol kubectl get all -n default + +# View monitoring stack +obol kubectl get all -n monitoring + +# View all Helm releases +obol helm list -A +``` + +## Accessing services + +Services are exposed via Traefik ingress on ports 8080 (HTTP) and 8443 (HTTPS). + +| Service | URL | +| --- | --- | +| Grafana | `http://grafana.localhost:8080` | +| Prometheus | `http://prometheus.localhost:8080` | + +:::info +The `obol.stack` hostname is added to `/etc/hosts` during installation, enabling local DNS resolution for stack services. +::: diff --git a/versioned_docs/version-v1.8/obol-stack/installing-networks.mdx b/versioned_docs/version-v1.8/obol-stack/installing-networks.mdx new file mode 100644 index 0000000000..e1cab0c208 --- /dev/null +++ b/versioned_docs/version-v1.8/obol-stack/installing-networks.mdx @@ -0,0 +1,277 @@ +--- +description: "Deploy blockchain networks on your local Obol Stack" +sidebar_label: "Installing Networks" +slug: /obol-stack/installing-networks +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Installing networks + +The Obol Stack supports installing multiple blockchain networks on your local Kubernetes cluster. Each network installation creates a unique deployment with its own namespace, allowing you to run multiple instances simultaneously. + +## Available networks + +View all available networks: + +```shell +obol network list +``` + +Currently supported networks: + +| Network | Description | +| --- | --- | +| **ethereum** | Full Ethereum node (execution + consensus clients) | +| **helios** | Ethereum light client for RPC access | +| **aztec** | Aztec Layer 2 sequencer node | + +## Network installation workflow + +Installing a network follows a two-step process: + +1. **Install** - Generate configuration and save to disk +2. **Sync** - Deploy the configuration to the cluster + +This separation allows you to review and modify configuration before deployment. + +### Install command + +```shell +obol network install [flags] +``` + +This creates a deployment directory at `~/.config/obol/networks///` containing: + +* `values.yaml` - Configuration values (editable) +* `helmfile.yaml.gotmpl` - Deployment definition + +### Sync command + +```shell +obol network sync / +``` + +This deploys the configuration to your Kubernetes cluster using Helmfile. + +### Delete command + +```shell +obol network delete / +``` + +This removes both the Kubernetes resources and local configuration. + +## Ethereum network + +Deploy a full Ethereum node with configurable execution and consensus clients. + +### Configuration options + +| Flag | Description | Options | Default | +| --- | --- | --- | --- | +| `--id` | Deployment identifier | Any string | Auto-generated | +| `--network` | Ethereum network | mainnet, sepolia, hoodi | mainnet | +| `--execution-client` | Execution layer client | reth, geth, nethermind, besu, erigon, ethereumjs | reth | +| `--consensus-client` | Consensus layer client | lighthouse, prysm, teku, nimbus, lodestar, grandine | lighthouse | + +### Examples + + + +Deploy an Ethereum node on Hoodi testnet with default clients: + +```shell +# Install configuration +obol network install ethereum --network=hoodi + +# Deploy to cluster (replace with your deployment ID) +obol network sync ethereum/knowing-wahoo +``` + + + +Deploy a mainnet node with Geth and Prysm: + +```shell +# Install with specific clients +obol network install ethereum \ + --id=mainnet-prod \ + --network=mainnet \ + --execution-client=geth \ + --consensus-client=prysm + +# Deploy to cluster +obol network sync ethereum/mainnet-prod +``` + + + +Run mainnet and testnet nodes simultaneously: + +```shell +# Install mainnet +obol network install ethereum --id=mainnet --network=mainnet + +# Install hoodi testnet +obol network install ethereum --id=hoodi --network=hoodi + +# Deploy both +obol network sync ethereum/mainnet +obol network sync ethereum/hoodi +``` + + + +:::warning +Full Ethereum nodes require significant resources. Mainnet execution clients need 1+ TB of storage and can take days to sync. Consider using testnets for development. +::: + +### Check sync status + +Monitor your Ethereum node sync progress: + +```shell +# View pod status +obol kubectl get pods -n ethereum- + +# Check execution client logs +obol kubectl logs -n ethereum- -l app=execution -f + +# Check consensus client logs +obol kubectl logs -n ethereum- -l app=consensus -f +``` + +## Helios light client + +Deploy a Helios Ethereum light client for fast RPC access without syncing a full node. + +### Configuration options + +| Flag | Description | Options | Default | +| --- | --- | --- | --- | +| `--id` | Deployment identifier | Any string | Auto-generated | +| `--network` | Ethereum network | mainnet | mainnet | +| `--consensus-rpc` | Consensus RPC endpoint | URL | Public endpoint | +| `--execution-rpc` | Execution RPC endpoint | URL | Public endpoint | + +### Example + +```shell +# Install Helios +obol network install helios + +# Deploy to cluster +obol network sync helios/ +``` + +Helios provides a local RPC endpoint that verifies data against the consensus layer, giving you trustless Ethereum access without running a full node. + +## Aztec network + +Deploy an Aztec Layer 2 sequencer node for the privacy-focused Ethereum rollup. + +### Configuration options + +| Flag | Description | Options | Default | +| --- | --- | --- | --- | +| `--id` | Deployment identifier | Any string | Auto-generated | +| `--network` | Aztec network | mainnet | mainnet | +| `--attester-private-key` | Attester private key (hex) | Required | None | +| `--l1-execution-url` | L1 execution RPC URL | URL | ERPC endpoint | +| `--l1-consensus-url` | L1 consensus RPC URL | URL | Public endpoint | + +### Example + +```shell +obol network install aztec \ + --attester-private-key= \ + --l1-execution-url=https://geth-prysm-mainnet-1.gcp.obol.tech/ \ + --l1-consensus-url=https://prysm-geth-mainnet-1.gcp.obol.tech/ +``` + +**What this does:** + +* Deploys an Aztec sequencer node in your local Kubernetes cluster. +* Connects to Ethereum mainnet using the specified RPC endpoints. +* Configures your node as an attester using the provided private key. + +**Default L1 RPC endpoints:** + +* **Execution Layer**: `https://geth-prysm-mainnet-1.gcp.obol.tech/` (Geth) +* **Consensus Layer**: `https://prysm-geth-mainnet-1.gcp.obol.tech/` (Prysm) + +These are production-grade, publicly accessible Ethereum nodes provided by Obol. + +:::info +You can use your own Ethereum node endpoints by changing the `--l1-execution-url` and `--l1-consensus-url` flags. +::: + +Deploy to the cluster: + +```shell +obol network sync aztec/ +``` + +### Resource requirements + +The Aztec sequencer requires significant resources: + +| Resource | Request | Limit | +| --- | --- | --- | +| **CPU** | 4 cores | 8 cores | +| **Memory** | 16 GB | 32 GB | +| **Storage** | 1 TB | - | + +:::warning +Ensure your machine has sufficient resources before deploying an Aztec node. The node requires substantial CPU, memory, and disk space for operation. +::: + +## Managing deployments + +### List installed networks + +View configuration directories: + +```shell +ls ~/.config/obol/networks/ +``` + +### View deployment status + +Check running deployments: + +```shell +obol kubectl get namespaces | grep -E "ethereum|helios|aztec" +``` + +### Modify configuration + +Edit the values file before syncing: + +```shell +# Open values.yaml in your editor +$EDITOR ~/.config/obol/networks///values.yaml + +# Re-sync to apply changes +obol network sync / +``` + +### Delete a deployment + +Remove a network deployment: + +```shell +obol network delete / +``` + +This deletes: + +* Kubernetes namespace and all resources +* Local configuration directory +* Persistent volume claims (data) + +:::warning +Deletion is permanent. All blockchain data stored in the deployment will be lost. +::: diff --git a/versioned_docs/version-v1.8/obol-stack/quickstart.mdx b/versioned_docs/version-v1.8/obol-stack/quickstart.mdx new file mode 100644 index 0000000000..55edd0e6e1 --- /dev/null +++ b/versioned_docs/version-v1.8/obol-stack/quickstart.mdx @@ -0,0 +1,215 @@ +--- +description: "Get started with Obol Stack in under 5 minutes" +sidebar_label: "Quickstart" +slug: /obol-stack/quickstart +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Quickstart + +This guide walks you through installing the Obol Stack and running your first blockchain network locally. + +## Prerequisites + +* Docker installed and running on your machine. +* macOS or Linux operating system. +* At least 8 GB of RAM available. +* Terminal access. + +:::info +Ensure Docker is running before proceeding. You can verify this by running `docker info` in your terminal. +::: + +## Step 1: Install Obol Stack + +Run the bootstrap installer to set up your environment: + +```shell +bash <(curl -s https://stack.obol.org) +``` + +The installer will: + +1. Validate prerequisites (Docker daemon). +2. Create the directory structure. +3. Install the `obol` CLI binary. +4. Install pinned versions of dependencies (kubectl, helm, k3d, helmfile, k9s). +5. Configure your PATH. +6. Add `obol.stack` to `/etc/hosts` (requires sudo). + +:::tip +The installer supports both interactive and non-interactive modes. For scripted installations, use environment variables like `OBOL_MODIFY_PATH=yes`. +::: + +### Installation options + + + +Standard installation using XDG Base Directory specification: + +```shell +bash <(curl -s https://stack.obol.org) +``` + +Files are installed to: + +* Config: `~/.config/obol/` +* Data: `~/.local/share/obol/` +* Binaries: `~/.local/bin/` + + + +Install a specific release version: + +```shell +OBOL_RELEASE=v0.1.0 bash <(curl -s https://stack.obol.org) +``` + + + +For contributors working on the Obol Stack codebase: + +```shell +git clone https://github.com/ObolNetwork/obol-stack.git +cd obol-stack +OBOL_DEVELOPMENT=true ./obolup.sh +``` + +Development mode uses a local `.workspace/` directory and runs `go run` instead of a compiled binary. + + + +## Step 2: Initialize and start the cluster + +Initialize the stack configuration: + +```shell +obol stack init +``` + +This generates a unique cluster ID and prepares the k3d configuration. + +Start the Kubernetes cluster: + +```shell +obol stack up +``` + +:::info +The first startup may take a few minutes as Docker pulls the required images for k3d and the default applications. +::: + +## Step 3: Verify the installation + +Check that the cluster is running: + +```shell +obol kubectl get nodes +``` + +You should see output similar to: + +``` +NAME STATUS ROLES AGE VERSION +k3d-obol-stack-xxxxx-server-0 Ready control-plane,master 1m v1.31.4+k3s1 +k3d-obol-stack-xxxxx-agent-0 Ready 1m v1.31.4+k3s1 +k3d-obol-stack-xxxxx-agent-1 Ready 1m v1.31.4+k3s1 +k3d-obol-stack-xxxxx-agent-2 Ready 1m v1.31.4+k3s1 +``` + +List available networks: + +```shell +obol network list +``` + +## Step 4: Install a network + +Install an Ethereum node on the Hoodi testnet: + +```shell +obol network install ethereum --network=hoodi +``` + +This creates a network configuration with an auto-generated deployment ID (e.g., `knowing-wahoo`). + +Deploy the network to the cluster: + +```shell +obol network sync ethereum/knowing-wahoo +``` + +:::warning +Replace `knowing-wahoo` with the actual deployment ID shown in your terminal output. +::: + +Check the deployment status: + +```shell +obol kubectl get pods -n ethereum-knowing-wahoo +``` + +## Step 5: Explore your cluster + +Use k9s for a visual interface to explore your cluster: + +```shell +obol k9s +``` + +Or check specific resources: + +```shell +# View all pods across namespaces +obol kubectl get pods -A + +# View logs for a specific pod +obol kubectl logs -n ethereum-knowing-wahoo + +# View persistent volume claims +obol kubectl get pvc -A +``` + +## Stopping and cleaning up + +### Stop the cluster + +To stop the cluster while preserving all data: + +```shell +obol stack down +``` + +### Restart the cluster + +To restart a previously initialized cluster: + +```shell +obol stack up +``` + +### Remove everything + +To completely remove the cluster and configuration: + +```shell +obol stack purge +``` + +:::warning +The `purge` command removes the cluster configuration. To also remove persistent data (blockchain data, PVCs), add the `-f` flag: + +```shell +obol stack purge -f +``` + +This action is irreversible. +::: + +## Next steps + +* [Installing networks](installing-networks.mdx) - Learn how to deploy different blockchain networks. +* [Installing apps](installing-apps.md) - Deploy additional applications on your stack. +* [FAQ](faq.md) - Common questions and troubleshooting. diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/README.md b/versioned_docs/version-v1.8/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..77e5bf9a25 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# integrations + diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.8/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..f9b23b72fb --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,58 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](../../learn/intro/launchpad.md) and other applications. + +### Pre-requisites {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) is required. + +### Create a SAFE to own the EigenPod {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](../start/create-a-dv-with-a-group.mdx) on the [DV Launchpad](../../learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. + diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.8/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..72b140c851 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/dappnode.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "Run a DV on a DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# DappNode + +For setup, see quickstart guide: + +For set-up of a DV using DappNode, see the quickstart guide [Create a DV Alone](../start/create-a-dv-alone.mdx), and select the appropriate tab for "DappNode". + +### Frequently asked questions {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster? {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC? {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically.\\ + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol? {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..fea4ee0cf3 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,225 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://operatorportal.lido.fi/modules/community-staking-module) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from Holesky just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using the CSM widget and expanding `Specify Custom Addresses` to set the `Manager Address` to the cluster multi-sig (SAFE) and the `Rewards Address` to the Splits.org splitting contract. Finally, we'll be selecting `Extended` permissions type which grants `Manager Address` ultimate control over the Node Operator. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (this can be the same address used in the SAFE contract). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (recommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol protocol development, thereby earning [Obol Incentives](https://obol.org/incentives) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [protocoldevelopmentfee.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol protocol development. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated the CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create validator keys with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create. +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using your favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM V2 enables a new Operator Type called Identified Community Staker ("ICS"). The squad member who is an ICS should be the one to create the node through the CSM widget. Doing so ensures the clusters validators receive [ICS benefits](https://blog.lido.fi/unlock-exclusive-benefits-as-an-identified-community-staker/). + +ICS member heads to [csm.lido.fi](https://csm.lido.fi/) and connects their wallet. + +![](/img/gitbook/image-47.png) + +The ICS member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The ICS member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The ICS member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button. + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-for-capital-allocators.md b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-for-capital-allocators.md new file mode 100644 index 0000000000..7c9dbfae12 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-for-capital-allocators.md @@ -0,0 +1,453 @@ +--- +sidebar_label: "For Capital Allocators" +slug: /run-a-dv/integrations/lido-v3-stvault-integration-kit/lido-v3-stvault-for-capital-allocators +--- + +# Capital Allocator Guide – Lido V3 stVault with Obol DVs + +--- + +## Quick Overview + +**Target audience:** ETH capital allocators – retail, treasuries, funds, ETF/ETP issuers, institutions. + +:::info +Obol's [Cluster-as-a-Service](https://hubs.ly/Q03Y2Srl0) offering can get you started quickly: we act as a trusted advisor, connect you with top node operators, and help guide decisions around validator sidecars and MEV strategies. +::: + +For a capital allocator, a **Lido stVault** provides a way to create a **dedicated, siloed ETH staking vault**: + +- you choose the **node operator set** (e.g. by geography, infrastructure used, reputation), +- you agree on **additional reward arrangements** (e.g. [ETH gas](https://www.ethgas.com/), [Primev](https://www.ethgas.com/), other DV compatible incentives), +- and you retain the option to tap into **stETH liquidity** at the vault level. + +That liquidity can then be used by a curator or strategy provider for things like **boosted APR via looping**, **restaking**, or other structured strategies – while the underlying validators are run by an **Obol Distributed Validator (DV) cluster** for operational resilience. + +--- + +## Definitions + +**stVaults** are Lido's staking "building blocks": isolated vaults that hold ETH, run validators, and (optionally) mint stETH under a configurable risk framework. Each vault has its own operator set and parameters, so risk and behavior are compartmentalized rather than shared across the entire protocol. + +On top of this, Obol provides **Distributed Validator Technology (DVT)**: validator keys and duties are spread across multiple independent operators/nodes rather than being concentrated on a single computer. + +### stVault terminology + +- **stVault** + + A Lido V3 vault that: + + - accepts ETH, + - funds validators on the beacon chain, and + - can optionally mint stETH under a specific tier configuration (Reserve Ratio + minting cap) for DeFi / strategy use. +- **Reserve Ratio (RR)** + + The percentage of vault value that must remain reserved as collateral when minting stETH. + + - No stETH can be minted for this reserved portion. + - Higher RR ⇒ more conservative, less minting capacity. + - Lower RR ⇒ more capital efficient, more minting capacity (within caps). +- **Tier** + + A risk configuration assigned to a Node Operator. A tier defines: + + - a **Reserve Ratio (RR)**, and + - a **maximum stETH minting cap** for vaults attached to that tier. +- **Default tier** + + The tier applied to vaults created by **non-identified** node operators: + + - fixed **RR = 50%**, + - conservative minting behavior, especially in early rollout phases. +- **DVT tiers** + + Tiers designed for vaults operated by **multi-operator DV clusters** (e.g. Obol). The current default DV vault schedule proposed in Lido's risk framework is: + + - **Tier 1** – up to 50,000 ETH used for minting capacity, **RR = 2%** → max ~49,000 stETH + - **Tier 2** – up to 50,000 ETH, **RR = 2%** → max ~49,000 stETH + - **Tier 3** – up to 200,000 ETH, **RR = 2%** → max ~196,000 stETH + - **Tier 4** – up to 300,000 ETH, **RR = 3%** → max ~291,000 stETH + - **Tier 5** – up to 400,000 ETH, **RR = 4%** → max ~384,000 stETH + + In total, these DVT tiers allow up to **969,000 stETH** to be minted on **1,000,000 ETH** of "mintable" value, reflecting higher capital efficiency than the Default 50% RR, while still enforcing explicit per-tier caps. + +- **Total Value** + + The sum of: + + - ETH staked in validators (including rewards), and + - ETH held in the vault's balance. +- **stETH Liability / Minting Capacity / Utilization / Health Factor** + + Core metrics Lido uses to track vault safety and usage: + + - **stETH liability** – how much stETH the vault has minted, + - **minting capacity** – how much more could be minted given RR and caps, + - **utilization** – what fraction of capacity is in use, + - **health factor** – how safely the vault is collateralized. + +### Obol terminology + +- **Distributed Validator (DV)** + + A validator whose signing key is split across multiple operator nodes. Duties are executed collaboratively through DV middlewares (for example, Obol's Charon or Nethermind's Pluto), so no single node holds the full key or can unilaterally control the validator. + +- **DVT (Distributed Validator Technology)** + + The underlying cryptographic and networking stack that makes DVs possible: threshold BLS signatures, distributed key generation, signature aggregation, peer to peer communication, and consensus components. + +- **DV cluster** + + A group of independent node operators jointly running one or more DVs. + + In the Lido stVault context, DVT categories typically assume: + + - **4 or more independent operators**, and + - validator keys generated via a DKG ceremony. +- **DKG (Distributed Key Generation)** + + A protocol that generates validator private keys collaboratively such that: + + - no single operator ever knows the full validator private key, and + - key shares can be used jointly to produce valid signatures. +- **Curator / Strategy provider** + + An entity responsible for the *economic* behavior of the vault: + + - deciding whether the vault is staking only, or using minted liquid staked tokens to generate further yield. + - designing and managing these further strategies (e.g., looping, hedging price risk, or other structured approaches). + + Obol can help connect depositors with suitable curators where an end-to-end solution is desired. + +--- + +## Comparison: Lido Core vs non-DV Vault vs Vault on Obol DVs + +| Dimension | Staking via Lido Core (no vault) | Staking with a Vault (no DV) | Staking with an Obol DV and a Vault | +| --- | --- | --- | --- | +| **What it is** | Stake directly through Lido Core; ETH is pooled and allocated across Lido's curated operator set. | ETH is deposited into a **dedicated stVault** with a chosen single node operator; vault can optionally mint stETH under a tier (RR + cap). | ETH is deposited into a **dedicated stVault** whose validators are run by a **multi-operator Obol DV cluster**; vault can target DVT-specific tiers over time. | +| **Risk isolation & scope** | Risk is **global** at the protocol level; underperformance or slashing impacts the broader Lido Core pool. | Each stVault is a **siloed risk container**; failures or misconfigurations are contained to that vault, not the global pool. But failure risk is higher due to lack of diversity of operators and clients. | Same per-vault isolation as a non-DV vault, **plus** risk is mitigated due to multiple operators inside the DV cluster sharing the staking duties. | +| **Operator model** | Operators are selected by Lido and managed via governance; you do **not** choose specific operators for your stake. | You select a **specific operator** (or operator entity) per vault and rely on them for security and resilience. But even the biggest operators can be [subject to attacks](https://www.theblock.co/post/370141/kiln-exits-ethereum-validators) despite their best practices. | You select or approve a **set of independent operators** forming a DV cluster. No one holds the entire private key, protecting your stake even when an operator is compromised. | +| **Operational resilience** | Resilience comes from Lido's **diversified operator set** at protocol scale, but each validator is still run by a single operator in the majority of cases. | Validator duties are typically run on a **single operator's stack**. A misconfig, hardware failure, or outage can significantly impact that vault's uptime and rewards. | Duties are distributed across a **DV cluster** (multiple operators/machines, often across geographies). The system is not down with one node/operator going offline. | +| **Tiers & Reserve Ratio (RR)** | You don't see or control tiers directly; you simply receive stETH and its yield. | Vault uses a **tier** (RR + cap). Non-identified operator vaults default to **50% RR** (Default tier) with conservative minting behavior. | Vault can qualify for **DVT tiers**: RR as low as **2–4%** with explicit per-tier minting caps (e.g. 5 tiers totalling 1,000,000 ETH "mintable" with 969,000 max stETH). It is 10+ times better than non-identified, non-DV vaults | +| **Access to DVT tiers** | No direct access: there's no per-vault DVT tier concept since you're staking into the global Lido Core pool. | Not DVT by design, so **no DVT tier** access; can only move from Default 50% RR to other non-DVT identified tiers (if/when operator qualifies). | DV cluster can be **identified** via Lido's Identified Node Operator process and attached to **DVT tiers**, providing a path from Default 50% RR to lower-RR, higher-efficiency tiers. | +| **Capital efficiency & strategies** | stETH/wstETH is liquid and can be used in DeFi, but there is no per-vault RR control; strategies are entirely external to Lido Core. | Vault can mint stETH subject to its RR and caps; with **50% RR**, leverage for looping/restaking is limited, so APR uplift over baseline staking is modest. | Low-RR DVT tiers enable **much higher minting capacity** for the same TVL, making looping/restaking strategies more capital efficient (e.g. meaningful APR uplift vs Default RR 50%). | +| **Strategy surface (looping, etc.)** | Strategy design is off-protocol; you use stETH in external DeFi venues. | Strategies can be layered at the vault level (via a curator), but constrained by higher RR if the operator isn't DVT-qualified. | Vault becomes a **strategy-friendly substrate**: DVT tiers with low RR + health metrics + multi-op resilience make it a natural base for looping, restaking, and structured products. | +| **Governance & customization** | Governance is at the Lido protocol level; you cannot customize per-pool economics or operator sets for your specific capital. | You can customize **governance, fees, and operator choice** per vault using roles (e.g. fund-specific or ETF-specific vaults with bespoke controls). | Same per-vault governance/customization but roles can be given to a multisig-Safe wallet for extra security across operators. | +| **Typical user / use case** | Users who want **simple, liquid staking** and are comfortable with protocol-wide diversification instead of bespoke vaults. They would like to actively manage their own strategies and calculate risks associated with it. | Capital allocators wanting **dedicated infrastructure** and configurable fees/parameters, but willing to accept **single-operator slashing and downtime risks**. | Capital allocators who want **dedicated vaults**, **multi-operator resilience**, a **governed path to DVT tiers (lower RR)**, and the option to run advanced strategies on top. | + +## Understanding impact of RR with an Example + +To illustrate how DVT RR if utilized properly can yield boosted APR, we compare three cases: + +1. **No looping** (pure staking) +2. **Looping on non-DVT vault** (50% mintable capacity) +3. **Looping on DVT vault** (98% mintable capacity) + +It must be noted that following calculations are only for illustrative purpose and numbers will vary with market conditions and risk appetite. To understand the calculations, refer to the appendix. + +**High-level outcomes** + +| Case | Mintable fraction | Effective leverage (≈ TVL / capital) | Approx. TVL in vault | Approx. total borrow | User APR (net) | +| --- | --- | --- | --- | --- | --- | +| No looping | 0% (no minting) | **1.0×** | 10,000 | 0 | **≈ 2.84%** | +| Looping – non-DVT vault (default RR) | 50% | **≈ 1.87×** | ≈ 18,687 | ≈ 8,687 | **≈ 3.16%** | +| Looping – DVT vault (DVT tier) | 98% | **≈ 7.22×** | ≈ 72,188 | ≈ 62,188 | **≈ 5.19%** | + +Where: + +- **Effective leverage** ≈ `Total vault value / Initial capital` +- **Total borrow** is the cumulative ETH borrowed from Aave and re-deposited into the vault. + +:::warning +Eth Staking APR and Eth borrow cost are variable. Borrowing cost can be higher than the staking APR, resulting in a negative APR from looping. Consult the appendix below for more information. +::: + +--- + +## How Should I Stake? – High-Level Decision Tree + +``` +Start + ├─→ Are you a retail user or an allocator who does NOT need a dedicated, isolated vault? + │ │ + │ ├─→ YES → Use a shared vault such as the Ethereum Client Team Vault + │ │ (pooled vault, boosted strategies, Primev rewards) + │ │ + │ └─→ NO → Continue ↓ + │ + └─→ Are you an ETF issuer, fund, DAO treasury, or institution that + requires segregation of ETH and custom governance/controls? + │ + ├─→ YES → Create a dedicated DVT stVault with Obol + │ (per-vault operators, governance, strategies) + │ + └─→ NO → Consider whether a DeFi-wrapper enabled vault already meets + your requirements; if in doubt, talk to Obol. + +``` + +--- + +## Path A: Shared DeFi-Wrapper Vault (Retail / Non-Dedicated) + +**Who this is for** + +- Retail users, DAOs, funds, or smaller treasuries that: + - don't need their **own dedicated vault**, and + - want exposure to **pooled strategies** with boosted rewards. + +**What you get** + +- A **DeFi-wrapper vault** (launching in January 2026) that: + - pools ETH from multiple users into an underlying stVault, + - is **run by Ethereum client teams** and curated by **Nethermind**, + - implements **boosted strategies** (e.g. looping, restaking), + - leverages **Primev** for additional rewards where applicable. + +**What you do** + +- Deposit ETH into the 'Ethereum Client Team Boosted Vault'. +- Receive the wrapper's token / position representing your share. +- Monitor: + - published strategy, + - net APR after fees, + - risk disclosures (health/LTV-style metrics where available). + +You **do not** need to handle: + +- vault creation, +- node operator selection, +- Obol DV cluster formation. + +All of that is handled by the client teams + Nethermind (strategy), with Obol DVT under the hood. + +--- + +## Path B: Dedicated DVT stVault with Obol (ETF / Treasury / Institutional) + +If you are an ETF issuer, large fund, DAO treasury, or any allocator that **does not want to pool ETH with other users** or have specific choice of operators, you will create a **dedicated DV stVault**. + +Obol will assist along the way: from design → DV cluster → identification → strategy. + +### Step 1 — Define the Vault and Its Controls + +**Who this is for** + +- Capital allocators that require: + - **segregated ETH**, + - specific governance (e.g. ETF board / DAO / foundation), + - audit-friendly parameterization (fees, roles, permissions). + +**Decisions you make** + +- **Product scope** + - *Staking-only*, or + - *Staking + optional liquidity/strategies* (e.g. looping, restaking, Primev, etc.). +- **RR / tier posture** + - Start at **Default 50% RR** (non-identified), with a plan to move to DVT tiers later, or + - Aim directly for DVT tiers via early alignment with Lido's DVT category. +- **Governance model** + - Multisig composition for: + - vault owner / governance safe, + - node operator safe, + - fee recipient / accounting. + - Emergency powers (pauses, exits). + - Fee parameters (node operator fee, any additional service/strategy fees). + +**What happens technically** + +- A **stVault** is deployed with: + - roles and permissions matching the above, + - a designated Node Operator entity (which will represent the DV cluster), + - initial tier attachment (typically defaults to 50% RR at launch). + +**How Obol helps** + +- Co-design of roles, safes, and failure modes. +- Helps you move from normal tier to a DVT tier through [Lido's identification process](https://docs.lido.fi/run-on-lido/stvaults/node-operators-identification/). +- Templates / examples for: + - governance policies, + - incident playbooks, + - fee configurations. +- Introduction to **curators / strategy providers** if you want an economic layer on top (beyond pure staking). + +:::info +For detailed identification process steps, see the [Node Operator Guide](lido-v3-stvault-for-node-operator.md#51-dv-cluster-identification-process). +::: + +--- + +### Step 2 — Assemble the DV Operators + +**Objective** + +Build a **DV cluster** that can qualify for Lido's **DVT category** and DVT tiers, while meeting your internal constraints (jurisdiction, infra diversity, etc.). + +**Requirements (high-level)** + +- **≥ 4 independent operators** (distinct entities). +- Validators run as **DVs**, not single-operator keys. +- Validator keys generated via **DKG**, so no single party ever sees the full key. +- Operational standards: + - monitoring, + - upgrade processes, + - on-call / incident response, + - SLAs. + +**What happens technically** + +- Candidate operators are selected and agree on operational expectations. +- An **Obol DV cluster** is created: + - DKG ceremony for validator keys, + - cluster configuration (Charon, clients, networking), + - metrics and alerting wired up. +- The DV cluster's structure and operational procedures are documented as part of the material needed for **Lido's Identified Node Operator process** (to attach DVT tiers later). + +**How Obol helps** + +- Maintains an ecosystem view of potential operators. +- Proposes **operator sets** that match: + - geography / jurisdiction preferences, + - infrastructure diversity (cloud vs bare metal, client diversity, etc.). +- Coordinates: + - DKG, + - cluster bootstrapping, + - best practices on monitoring and upgrades. +- Prepares technical input for the **Identified Node Operator** submission (DVT category). + +For detailed steps on the identification process, see the [Node Operator Guide](lido-v3-stvault-for-node-operator.md#51-dv-cluster-identification-process). + +--- + +### Step 3 — Strategies and Additional Rewards (Optional) + +This step is optional and only applies if you want more than the **baseline staking yield**. + +**Decisions you make** + +- Whether to: + - keep the vault **staking-only**, or + - allow **minted stETH** to be used in strategies (looping, hedged positions, restaking, Primev, etc.). +- Your comfort with: + - leverage/looping levels, + - borrow rate risk, + - extra smart contract and integration risk. + +**What happens technically** + +- A **curator / strategy provider** designs a strategy that: + - respects the vault's RR and DVT tier caps, + - stays within safe **health / utilization** bounds, + - integrates any sidecars (e.g. Primev) for extra rewards. +- The strategy is executed at the vault level: + - minting stETH (within capacity), + - routing it into external protocols, + - managing rebalances and unwinds. +- Health metrics (utilization, health factor) are monitored; corrective actions are defined in advance. + +**How Obol helps** + +- Connects you with **curators** who have relevant experience (looping, restaking, market-neutral, etc.). +- Provides **operational constraints** from the validator side: + - how often it is safe to rebalance without stressing infra, + - how exits/redemptions map to validator exit queues. +- Works alongside the curator to ensure the strategy is compatible with: + - cluster operations, + - Lido's risk framework, + - your internal risk policies. + +## Appendix + +### Parameters Used + +| Category | Parameter | Value | +| --- | --- | --- | +| User | Initial capital | **10,000** | +| stVault economics | stVault gross yield | **3.15%** | +| | Node operator fee | **2.0%** (of staking yield) | +| | Obol fee | **0.5%** (of staking yield) | +| Lido fees | Lido infra fee | **1.0%** (of staking yield) | +| | Lido liquidity fee | **6.5%** (of staking yield) | +| | Total fee share | **10.0%** of staking yield | +| | **Net base APR to user** | **≈ 2.84%** (no looping) | +| stETH reference | stETH gross yield | **3.0%** (context only) | +| Vault tier | Mintable capacity (DVT) | **98%** of vault value | +| | Mintable capacity (non-DVT) | **50%** of vault value | +| Aave / looping | Loops | **10** | +| | wstETH LTV | **93%** | +| | wstETH supply APY | **0.04%** | +| | ETH borrow cost | **2.5%** | + +For the example we compress all staking-side fees into a single **net base yield**: + +``` +stVault gross yield = 3.15% +Total fee share on yield = 1.0% + 6.5% + 2.0% + 0.5% = 10.0% + +Net base APR to user (no looping) +r_base_net = 3.15% × (1 − 10%) ≈ 2.835% + +``` + +So with *no looping*, a 10,000 deposit would earn ≈ 2.84% APR. + +--- + +### How the APR Is Calculated (Conceptual) + +For each case with looping we approximate: + +``` +Profit ≈ TV × r_base_net + minted_stETH × r_supply − borrowed_ETH × r_borrow + (staking on TV) (Aave supply APY) (borrow cost) + +User APR ≈ Profit / Initial capital + +``` + +Using: + +- `r_base_net ≈ 2.835%` (net staking APR to user, from the stVault) +- `r_supply = 0.04%` (wstETH supply APY on Aave) +- `r_borrow = 2.5%` (ETH borrow cost) + +### Case B – Non-DVT vault (50% mintable) + +After 10 loops: + +- `TV ≈ 18,687` +- `minted_stETH ≈ 9,341` +- `borrowed_ETH ≈ 8,687` + +Approximate annual profit: + +- Base staking: `18,687 × 2.835% ≈ 530` +- Aave supply: `9,341 × 0.04% ≈ 3.7` +- Borrow cost: `8,687 × 2.5% ≈ 217` + +``` +Profit ≈ 530 + 3.7 − 217 ≈ 316 +APR_default ≈ 316 / 10,000 ≈ 3.16% + +``` + +### Case C – DVT vault (98% mintable) + +After 10 loops: + +- `TV ≈ 72,188` +- `minted_stETH ≈ 66,869` +- `borrowed_ETH ≈ 62,188` + +Approximate annual profit: + +- Base staking: `72,188 × 2.835% ≈ 2,046` +- Aave supply: `66,869 × 0.04% ≈ 26.7` +- Borrow cost: `62,188 × 2.5% ≈ 1,555` + +``` +Profit ≈ 2,046 + 26.7 − 1,555 ≈ 518.6 +APR_DVT ≈ 518.6 / 10,000 ≈ 5.19% + +``` diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-for-node-operator.md b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-for-node-operator.md new file mode 100644 index 0000000000..70b153dea2 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-for-node-operator.md @@ -0,0 +1,506 @@ +--- +sidebar_label: "For Node Operators" +slug: /run-a-dv/integrations/lido-v3-stvault-integration-kit/lido-v3-stvault-for-node-operator +--- + +# Node Operator Guide – Operating a Lido V3 stVault with an Obol DV Cluster + +:::info +**Scope:** This guide is for node operators who operate a **Lido V3 stVault** with an **Obol Distributed Validator (DV) cluster**. + +It assumes: + +- stVault creation is done via **Lido's stVault UI** or **Lido's stVault CLI**, and +- validator operations (deposit, exit, withdrawal, etc.) are performed using **Lido stVault CLI or Lido's stVault UI** only. + +Reserve ratio benefits require **multi-operator DV vaults**. Single-operator setups do not qualify you for improved reserve ratios (though may qualify you for Obol's [Incentive](https://obol.org/incentives) program). +::: + +--- + +## 1. High-Level Flow (Multi-Operator Obol DV Vaults) + +At a high level, the lifecycle for a multi-operator Obol DV stVault is: + +1. **Create the stVault** + + – via **Lido stVault UI** (recommended where available) or **Lido stVault CLI**. + +2. **Set up governance & fee routing** + + – Configure a `GOVERNANCE_SAFE` and `NODE_OPERATOR_SAFE` using Gnosis's [Safe UI](https://app.safe.global/) as well as a `FEE_SPLIT_CONTRACT` using the [splits.org](http://splits.org) UI. + +3. **Create and publish the Obol DV cluster** + + – Use the `charon create dkg --publish` command or the [DV Launchpad](https://launchpad.obol.org/) to create a multi-operator DV cluster with the vault as both the withdrawal and fee recipient addresses. Use the `--operator-addresses` flag to invite the Node Operators to complete the DKG ceremony. + +4. **Run and monitor the DV cluster** + + – using Obol’s observability stack. + +5. **Monitor the vault** + + – using **Lido stVault CLI** (`contracts dashboard` and `vo` read commands) plus the stVault UI. + +6. **Distribute rewards and fees** + + – from the vault to the split contract, and from the split contract to participants (including Obol). + + +--- + +## 2. Creating the Vault (UI vs CLI) + +You can create a stVault in two ways: + +- **Lido stVault UI (recommended)** + - Hoodi testnet UI: `https://stvaults-hoodi.testnet.fi/` + - Mainnet stVault UI link will follow Lido’s official docs once live. +- **Lido stVault CLI** + - Main docs and command reference: + + `https://lidofinance.github.io/lido-staking-vault-cli/` + + +The CLI exposes two main entry points you will use: + +- `vo` – **vault-oriented commands** (lower-level, contract-centric). +- `contracts dashboard` – **dashboard-oriented commands** (product/UX layer, usually nicer for day-to-day). + +**Practical split:** + +- Use **`contracts dashboard r overview / health / info` as your primary monitoring entrypoint** (per vault “product”). +- Use **`vo r overview / health / info / roles`** when you need contract-level detail, addresses, or role debugging. + +:::warning +For beacon-chain deposits, validator exits, withdrawals and other stVault operations, use the Lido stVault UI or Lido stVault CLI only. + +Do **not** use the Obol Launchpad UI for these validators. +::: + +For the rest of this guide we assume a **multi-operator DV vault** with, for example: + +- **Cluster size:** 4 operators +- **Cluster limit:** up to ~1,000,000 ETH (subject to Lido risk / tier approvals) +- **Validator max stake:** 1,920 ETH per validator (allowing space for compounding) +- **Total validators:** ~520–600 in a full configuration + +These values are **illustrative**; actual limits depend on your and your depositor’s risk framework and governance. + +--- + +## 3. Core On-Chain Addresses & Safes + +Before (or alongside) vault creation, set up three core components. + +### 3.1 Governance Safe (`GOVERNANCE_SAFE`) + +- **Role:** vault owner / governance multi-sig. +- **Where to create:** + - Mainnet: `https://safe.global/` + - Hoodi testnet: Protofire Safe UI – `https://app.safe.protofire.io/` +- **Example policy:** + - 3/4 multi-sig across: + - client / treasury signers and/or + - operator representatives. + - Typically used as: + - **Vault Owner** + - **Default Admin / Node Operator Manager** + +--- + +### 3.2 Node Operator Safe (`NODE_OPERATOR_SAFE`) + +- **Role:** operational multi-sig for day-to-day validator + vault actions. +- **Where to create:** + - Mainnet: `https://safe.global/` + - Hoodi: `https://app.safe.protofire.io/` +- **Example policy:** + - 3/4 multi-sig across node operators and/or client infra. +- **Typical responsibilities:** + - Funding the vault + - Depositing to beacon chain + - Requesting validator exits + - Triggering withdrawals + - Initiating rebalances + - Minting/burning stETH if allowed by governance + - Interacting with Lido stVault contracts via CLI + +--- + +### 3.3 Fee Split Contract (`FEE_SPLIT_CONTRACT`) + +On **mainnet**, Obol’s protocol fee is enforced via a fee splitting contract: + +- Create via the **Splits.org UI**: `https://app.splits.org/` +- Configure: + - **1% of validator rewards → Obol protocol fee address** + + `0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d` + + - Remaining percentage split between operators according to your commercial terms. + +On **Hoodi**, Splits may not be available or may not support that network: + +- You may **skip the split contract** on testnet. +- On mainnet, **using a split contract that routes 1% of validator rewards to Obol is required** to earn Obol's incentive rewards. If this vault will be extremely significant, consider reaching out to the Obol core team to discuss the potential for a custom arrangement. + +The image below shows using the splits UI to create a split contract where 5% of validator rewards will be distributed equally across the 4 node operators and Obol. + +![](/img/gitbook/SPLITS-UI-RECIPIENTS.png) +
Example split contract configuration
+ +:::info +Consider setting the controller for this split contract to `NODE_OPERATOR_SAFE` or `GOVERNANCE_SAFE` to retain the ability to modify it at a later date. +::: + +--- + +## 4. Recommended Vault Parameters & Roles + +When creating the vault via UI or CLI, we recommend the following mapping. + +### 4.1 Main Settings (Vault Parameters) + +- **Node Operator:** `NODE_OPERATOR_SAFE` + + Entity responsible for validator operations and day-to-day vault actions. + +- **Vault Owner:** `GOVERNANCE_SAFE` + + Controls vault ownership, high-level parameters, and emergency controls. + +- **Node Operator Manager:** `GOVERNANCE_SAFE` + + Oversees the Node Operator; can be a separate address if required by governance. + +- **Node Operator Fee Recipient:** `FEE_SPLIT_CONTRACT` + + Set **after vault creation** so all node-operator fees route through the splitter. + +- **Node Operator Fee:** typically **3–10%** (expressed in basis points in the UI / CLI). +- **Confirmation Lifetime:** e.g. **48 hours** + + Relevant if `Vault Owner` and `Node Operator Manager` differ; defines how long confirmations are valid for sensitive operations. + + +For the latest flags and options when creating a vault, refer to: + +**Lido stVault CLI – `vo` commands** + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations` + +--- + +### 4.2 Role Assignments & Responsibilities (Recommended) + +| Address | Type | Permissions (examples) | Duties (examples) | Notes | +| --- | --- | --- | --- | --- | +| `GOVERNANCE_SAFE` | Multi-sig (e.g. 4/5) | Grant / revoke roles, transfer vault ownership, set confirmation expiry, pause / resume deposits, recover stuck assets, change node operator, set fee rates. | Strategic governance, emergency handling, fee structure oversight, monitoring node-operator performance, asset recovery. | Primary governance. Often also the node operator manager and vault owner. | +| `NODE_OPERATOR_SAFE` | Multi-sig (e.g. 3/4) | Deposit ETH to beacon chain, manage validator operations, trigger withdrawals, request exits, rebalance vault, monitor performance, claim node-operator fees. | Day-to-day vault and validator operations, responding to alerts, maintaining uptime and SLAs. | Single operational entry-point; should follow strict runbooks and operational policies. | +| `FEE_SPLIT_CONTRACT` | Smart contract | Anyone can call **distribute** to disburse the funds. | Receive node-operator fee rewards, splits across participants. | Obol gets 1% fee share via its protocol address; or as per commercial agreement. | + +These are **recommendations**, not stVault requirements; adapt to your own governance needs and risk appetite. + +--- + +## 5. Obol DV Cluster Setup (Multi-Operator Only) + +After the vault and core addresses exist, you can set up the **Obol DV cluster**. + +Follow Obol’s docs for **multi-operator DV setup**: + +- **Cluster size:** minimum 4 independent operators recommended +- **Compounding validators:** `true` (recommended for vault integrations). +- **Withdrawal address:** vault withdrawal address. +- **Fee recipient address:** vault / dashboard address. +- **Number of validators:** sized to your capacity and Lido-approved tier. + +Obol cluster creation docs: + +[Create a DV With a Group](../start/create-a-dv-with-a-group.mdx) + +:::info +When generating the cluster lock, use the --publish flag so the cluster lock is published and verifiable by: + +- DV participants, +- Lido risk review & DV tier evaluation, and for +- Better support by the Obol Team in troubleshooting cluster issues. +::: + +![](/img/gitbook/LIDO-STVAULT-OVERVIEW.png) + +![](/img/gitbook/CUSTOM-WITHDRAWAL-CONFIG.png) + +### 5.1 DV Cluster Identification Process + +After creating and publishing your Obol DV cluster, you must go through **Lido's identification process** to be classified as an **Obol DV cluster** and qualify for DV-specific tiers with improved Reserve Ratio (RR) and stETH minting limits. + +**Why identification matters:** + +- **Unidentified clusters** default to the **Default tier** with only a **50% Reserve Ratio** and limited stETH minting capacity. +- **Identified DV clusters** can qualify for **DV tiers** with **Reserve Ratios as low as 2-4%** and significantly higher stETH minting limits. + +For detailed tier breakdowns and capital efficiency benefits, see the [Capital Allocator Guide](lido-v3-stvault-for-capital-allocators.md#stvault-terminology). + +**The identification process:** + +1. Each individual Node Operator in the cluster must complete the identification process (post on Lido Research Forum, complete identification forms). +2. A cluster representative posts a **DV Cluster identification request** on the Lido Research Forum. +3. The representative completes the **DV Cluster Questionnaire** with technical and business information. +4. The stVaults Committee assesses your cluster and assigns a **category and tier grid**. +5. Once identified, your cluster can access DV-specific tiers with improved economics. + +**How Obol can help:** + +- Obol provides guidance and support throughout the identification process. +- We can help coordinate the cluster identification request and questionnaire completion. +- We assist with technical documentation and cluster structure details required for the assessment. + +For detailed information about the identification process, requirements, and tier structures, refer to [Lido's Node Operators Identification documentation](https://docs.lido.fi/run-on-lido/stvaults/node-operators-identification). + +--- + +## 6. Monitoring (DV Cluster & Vault) + +### 6.1 Obol DV Monitoring + +For DV-specific monitoring (RAVER, attestations, client health, etc.), use Obol’s monitoring stack: + +Obol monitoring docs: [Monitoring Your Own Node](../running/monitoring.md), [Sending metrics to Obol](../start/obol-monitoring.mdx) + +Typical components: + +- Metrics (e.g. Prometheus) for: + - attestation success + - proposer success + - Charon peer connectivity + - execution and consensus client health +- Alerts for: + - missed duties + - insufficient peers + - clients offline + - RAVER dropping below your target (e.g. 98%, if that’s your internal standard) + +Operators should agree on: + +- shared alert channels (Slack / Telegram / Discord), and +- explicit SLAs (who responds, how quickly, escalation path). + +--- + +### 6.2 Vault Monitoring (Using Lido stVault CLI) + +The **Lido stVault CLI** exposes read-only commands that are essential for operators and vault managers. + +CLI docs root: + +`https://lidofinance.github.io/lido-staking-vault-cli/` + +You will typically use: + +- **`contracts dashboard` read commands** for primary monitoring, and +- **`vo` read commands** for lower-level details and role inspection. + +### 6.2.1 Dashboard-Centric View (Recommended UX) + +For everyday operations, prefer the **dashboard** read commands: + +```bash +# Dashboard overview +yarn start contracts dashboard r overview + +# Dashboard health +yarn start contracts dashboard r health + +# Dashboard info (addresses, parameters, vault bindings) +yarn start contracts dashboard r info + +``` + +These provide a product-level view of: + +- vault health & status +- key parameters and addresses +- high-level metrics relevant to the specific “vault product” + +Docs: + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard` + +--- + +### 6.2.2 Vault-Level View (`vo` – Advanced / Low-Level) + +For underlying vault configuration and debugging, use `vo`: + +```bash +# Vault overview (contract-level) +yarn start vo r overview -v + +# Quick health check +yarn start vo r health -v + +# Roles and permissions +yarn start vo r roles -v + +# Core vault info (fee parameters, limits, addresses, etc.) +yarn start vo r info -v + +``` + +Docs: + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations` + +In practice: + +- **Dashboard commands** → main UX surface for operators. +- **`vo` commands** → used when you need full contract detail or to diagnose odd behavior. + +--- + +### 6.2.3 Performance Metrics (`metrics` namespace) + +Use the `metrics` namespace for APR and rewards analysis: + +```bash +# Comprehensive statistics (APR & rewards) +yarn start metrics r statistic + +# APR history (simplified text mode) +yarn start metrics r charts-apr --simplified + +# Rewards distribution charts +yarn start metrics r charts-rewards + +``` + +Docs: + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/metrics` + +Use these for: + +- performance reviews +- sanity-checking expected vs realized APR +- understanding the effect of DV tiers and any strategy layer + +--- + +### 6.3 Example Alerting Rules (Non-Canonical) + +:::info +The thresholds below are illustrative only. + +They are not official Lido nor Obol requirements and should be tuned to your vault's risk profile, product design, and the latest protocol guidance. +::: + +Examples of vault-level alerts you might configure: + +- **Health factor approaching 100%** + - Trigger an alert when health factor trends down into a “warning band” you define (for example, somewhere below x% according to your strategy), so you have time to respond before it reaches unsafe levels. +- **High utilization of mint capacity** + - Alert when utilization ratio is close to full (for example, above your internal high-water mark), indicating the vault is near its minting / leverage limit. +- **Low immediate liquidity** + - Alert when “available to withdraw” ETH falls below an internal buffer — for instance, less than one or two validators’ worth of ETH, depending on how your product handles withdrawals. +- **Sustained underperformance vs expectation** + - Alert when net staking APR stays materially below your internal target range for multiple reporting periods (e.g. several `metrics r statistic` runs in a row). +- **Low operational efficiency** + - Alert when net APR / gross APR (efficiency) drops below your chosen target, signalling that penalties, slashing, or high costs are eroding returns more than expected. + +**Cadence (example only):** + +- Health & dashboard checks: **at least daily**, ideally via automated alerts. +- Performance statistics (`metrics r statistic`): **weekly**. +- APR / rewards charts (`metrics r charts-apr / charts-rewards`): **monthly or quarterly** reviews. + +--- + +## 7. Deposits, Exits, Withdrawals (Pointers Only) + +This guide intentionally **does not duplicate** the full stVault operations surface. For: + +- **Beacon-chain deposits** (funding validators), +- **Validator exits**, +- **Triggering withdrawals**, +- **Withdrawing ETH from the vault to treasury**, +- **Minting / burning stETH or wstETH**, + +use the **Lido stVault CLI** docs: + +- Dashboard write commands (deposits, exits, etc.): + + [`https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write`](https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write) + +- Vault / VaultHub / additional commands: + + [`https://lidofinance.github.io/lido-staking-vault-cli/category/commands/`](https://lidofinance.github.io/lido-staking-vault-cli/category/commands/) + + +This keeps your operational runbooks aligned with the latest Lido contracts and CLI behaviour. + +--- + +## 8. Fees, Splits & Obol Incentives + +### 8.1 From Vault to Fee Splitter + +Step 1: disburse **node operator fees** from the vault/dashboard to `FEE_SPLIT_CONTRACT` using the Lido CLI. + +1. (Optional) Inspect vault info: + + ```bash + yarn start vo r info -v + ``` + +2. Disburse node-operator fees to the configured `feeRecipient` (your splitter) using the **dashboard write** command: + + ```bash + yarn start contracts dashboard w disburse-node-operator-fee \ + + ``` + + +Dashboard write docs: + +[`https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write`](https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write) + +This moves accrued node-operator fees from the vault to your `FEE_SPLIT_CONTRACT`. + +Hoodi link: https://stvaults-hoodi.testnet.fi/vaults/your_vault_address/claim + +--- + +### 8.2 From Splitter to Participants + +Step 2: **distribute and claim** via Splits.org: + +1. Open the **Splits.org UI**: [`https://app.splits.org/`](https://app.splits.org/) +2. Navigate to the page for your `FEE_SPLIT_CONTRACT` address. +3. Connect your wallet and choose either to: + - **Distribute** – moves the contract’s balance into recipients’ claimable balances. + - **Distribute and Withdraw** – moves the contract's balance into each participant's own address or Safe. Skipping their requirement to claim. + +Hoodi Link: Not available +Mainnet Link: `https://app.splits.org/accounts/` + +--- + +### 8.3 Obol Rewards (Protocol Incentives) + +If the split contract is configured correctly with Obol’s share of validator rewards, **Obol incentives** can be claimed proportionally via the [Obol DV Launchpad](https://launchpad.obol.org/) by the other addresses in the split: + +Process: + +1. Connect the **recipient wallet / Safe** that's entitled to the reward on the [DV Launchpad](https://launchpad.obol.org/). +2. Click the "Dashboard" button. +3. Claim any available Obol incentives. + +:::info +The DV Launchpad can also be used by Operators to claim their outstanding wstEth rewards once someone has distributed them from the split contract to make them claimable. +::: + +Hoodi Link: [https://hoodi.launchpad.obol.org/cluster/list/](https://hoodi.launchpad.obol.org/cluster/list/) + +Mainnet Link: [https://launchpad.obol.org/cluster/list/](https://launchpad.obol.org/cluster/list/) diff --git a/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-integration-kit.md b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-integration-kit.md new file mode 100644 index 0000000000..b447cf8e42 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/integrations/lido-v3-stvault-integration-kit.md @@ -0,0 +1,107 @@ +--- +sidebar_label: "Create a Lido stVault" +slug: /run-a-dv/integrations/lido-v3-stvault-integration-kit +--- + +# Create a Lido stVault + +:::info +💡 + +Lido V3 introduces **stVaults** — customizable staking vaults that unlock stETH liquidity for institutional stakers and asset managers. **Obol Distributed Validators offer the most capital-efficient way to deploy an stVault**, unlocking the **highest minting capacity** and the end game staking configuration. +::: + +## Create a Lido stVault + +**Target audience:** Node operators and capital allocators looking to deploy stVaults with **maximum capital efficiency** and institutional-grade security. + +:::info +**I'm a Node Operator**\ +Show me how to implement a DV-backed stVault.\ +[Open the Node Operator Guide](lido-v3-stvault-for-node-operator.md) +::: +:::info +**I'm a Capital Allocator**\ +Why should I use DV as infrastructure for my stVault.\ +[Open the Capital Allocator Guide](lido-v3-stvault-for-capital-allocators.md) +::: +:::info +**I Want Help from Obol**\ +[Connect with the Obol team](mailto:lido@obol.tech) or explore our [Cluster-as-a-Service](https://hubs.ly/Q03Y2Srl0) offering.
+::: +### Who This Kit Is For + +**Node operators** who are: + +* Being asked to **deploy, and operate** an stVault for a fund, DAO, protocol, or other allocator +* Building that vault on top of a **multi-operator Obol DV** rather than a single operator / single client setup + +**Capital allocators** who: + +* Need to understand **why** a DV-backed stVault can support more favorable risk assessments and reserve ratios +* Want a clear checklist for vetting operators and understanding what strong DV cluster operations look like + +### Why Obol DVs Are the Best Way to Deploy an stVault + +Lido V3's stVault design unlocks new levels of **capital efficiency** for node operators and institutional stakers. Obol Distributed Validators are **the most capital-efficient way to run a vault on Lido V3**. + +One of Lido V3's key innovations is the **Reserve Ratio (RR)**, which determines how much ETH must be kept as a reserve buffer relative to minted stETH. Lido is proposing a **2% Reserve Ratio tier for verified multi-operator DV vaults**, allowing up to **98% stETH minting capacity**. This is the most favorable tier. By comparison, the next-highest default tier for identified operators proposes a 5% RR with only 95% minting capacity. + +**Obol Distributed Validators unlock the highest minting capacity available on Lido V3.** + +#### Key Benefits + +* **Unlock the highest capital efficiency**\ + Multi-operator DV vaults qualify for the 2% Reserve Ratio tier, offering 98% stETH minting capacity, the most capital-efficient configuration on Lido V3. +* **Distribute responsibility across multiple operators**\ + Reduce reliance on any single infrastructure provider, company, or jurisdiction. Multi-operator setups distribute private key shares across many entities. +* **Maximize client and implementation diversity**\ + Run multiple consensus and execution client combinations inside the same vault, strengthening the vault's resilience and reducing correlation risks. +* **Superior liveness and fault tolerance**\ + Obol's fault-tolerant infrastructure means your validators keep performing even if individual operators experience downtime or failures. +* **Enterprise-grade security**\ + Leverage best-in-class security that institutional stakers and asset managers require for managing significant stake. + +### 📚 How This Integration Kit Is Organized + +#### For Node Operators – Implementation Guide + +A practical guide to designing, deploying, and operating an stVault using Obol DVs, including: + +* What to collect from the vault owner +* How to design your DV cluster (operators, clients, geos) +* How to rehearse on testnet and prepare for mainnet launch +* How this integrates into the Lido V3 stVault flow + +👉 [**Read the Node Operator Guide →**](lido-v3-stvault-for-node-operator.md) +#### For Capital Allocators – Design & Risk Overview + +A higher-level walkthrough of: + +* What you are optimizing for (safety, yield, minting capacity, counterparty risk) +* Why multi-operator DVs are different from "just another node operator" +* How Obol's [**Cluster-as-a-Service**](https://hubs.ly/Q03Y2Srl0) offering can help guide your decisions +* What to ask from your operators or from Obol directly + +👉 [**Read the Capital Allocator Guide →**](lido-v3-stvault-for-capital-allocators.md) +#### Support & Services for stVault Builders + +How to: + +* [Get in touch with the Obol team](mailto:lido@obol.tech) for guidance and design help +* Leverage Obol's [**Cluster-as-a-Service**](https://hubs.ly/Q03Y2Srl0) offering to get set up +### 🔗 Quick Links + +* [**Default risk assessment framework**](https://research.lido.fi/t/default-risk-assessment-framework-and-fees-parameters-for-lido-v3-stvaults/10504) — Explore how Tiers within Identified Node Operators effect the reserve ratio of the vault +* [**DV Cluster identification and assessment**](https://docs.lido.fi/run-on-lido/stvaults/node-operators-identification/#dvt-cluster-identification-and-assessment) — See the identification requirements for each node operator in a cluster in order to qualify for improved Tiering +* [**stVaults Doc Center**](https://docs.lido.fi/run-on-lido/stvaults/) — View Lido's comprehensive guides which detail how to create any product powered by stVaults + +#### Future Extensions + +As Lido's [**DeFi wrapper**](https://hackmd.io/@lido/lido-v3-wrapper-design) and more advanced strategies roll out, we will extend this kit with: + +* End-to-end reference architectures that combine stVaults, wrappers, and multi-operator DV clusters +* Config and deployment examples taken from real-world vaults +* Case studies, including the "Ethereum client team vault", once it is live + +**For now, this page gives you the map. The linked sections show you how to actually build and run the vaults behind it.** diff --git a/versioned_docs/version-v1.8/run-a-dv/prepare/README.md b/versioned_docs/version-v1.8/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..6d77f77e82 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# prepare + diff --git a/versioned_docs/version-v1.8/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.8/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..da8f61b1da --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,99 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10mb/s internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25mb/s internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimise both performance and cost-effectiveness, it is recommended to prioritise physical over virtualised setups. Such configurations typically offer greater performance and minimise overhead associated with virtualisation, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimise Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimize potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes would potentially impact the fault tolerance of the cluster and as a result should be avoided. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. Be sure to use encrypted communication between your VC and the Charon client, potentially through a cloud-provided network, a self-managed network tunnel, a VPN, a Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), or other manner. + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration/#cluster-size-and-resilience)). + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](./test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +The clusters should consist of a combination of your preferred consensus, execution, and validator clients. It is recommended to include a combination of multiple clients in order to have a healthy client diversity within the cluster, ideally, if any single client type fails, it should be less than the fault tolerance of the cluster, and the validators should stay online/not do anything slashable. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Metrics Monitoring + +As requested by Obol Labs, node operators can push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. Our recommendation for operators is to independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (usually < 24 hours). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.8/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.8/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..1c94049a40 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatibility information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.8/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.8/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..c223364b08 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,654 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + + +:::tip + +Adding the `--publish` flag to the below commands, and running the command from the directory containing your `.charon` folder, will submit the test results to the [Obol API](../../api/what-is-this-api.md). Publishing your performance reports grows the staking node dataset, and allows Obol and Ethereum development teams to make data-driven choices regarding the required specs for validating Ethereum. We hope you will consider opting in. + +::: + + + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + + +:::info + +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the `beacon` node and `validator` client tests, you need to point them toward the correct Docker container, this includes specifying the Docker container’s network. Check your docker networks with the command `docker network ls`. When you run the test command, specify the Docker network with `--network `. + +Read more about docker networking [here](https://docs.docker.com/engine/network/). + +::: + +#### Test all + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.8.0 alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.8.0 alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + + + + +#### Pre-requisites + +The executable storage tests require `fio` to be installed on your host machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +#### Example run + +```sh +charon alpha test infra +``` + + + + + +#### Example run + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.8.0 alpha test infra \ + --disk-io-test-file-dir=/opt/charon/test +``` + + + diff --git a/versioned_docs/version-v1.8/run-a-dv/running/README.md b/versioned_docs/version-v1.8/run-a-dv/running/README.md new file mode 100644 index 0000000000..515e6cbede --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# running + diff --git a/versioned_docs/version-v1.8/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.8/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..3c7cddf6d9 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +Use any of the following tools to deposit. Please use the third-party tools at your own risk and always double check the staking contract address. + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. diff --git a/versioned_docs/version-v1.8/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.8/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..ecba21a0e6 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/running/claim-rewards.md @@ -0,0 +1,65 @@ +--- +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +## Introduction + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator’s withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +The method for claiming rewards depends on the Cluster's withdrawal configuration, whether it's an [**OWR**](../../learn/intro/obol-splits.md#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](../../learn/intro/obol-splits.md#obol-validator-managers) . The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +\\ + +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](../integrations/lido-csm.md). | + +### Claim Flow {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](../../learn/intro/obol-splits.md). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +1. All validator rewards are accumulated in the validator's withdrawal address, which is a split wallet. +2. Claims can be triggered in two ways: + 1. **From addresses in the Splitter**: Splitter addresses will see a `Claim All` button. When the first address (e.g., address A) executes `Claim All`, it triggers a multi-call transaction to distribute rewards from all the split wallets associated with a cluster into the Split Main. The Split Main then sends address A’s proportion of the rewards (based on the split configuration at the time of cluster creation). All of this is executed with a single click for the first address. + 2. **From addresses not in the Splitter**: Non-splitter addresses will see a `Distribute All` button instead of `Claim All`. These addresses cannot claim rewards directly but can distribute rewards to the Split Main (subsidizing transaction fees for others). Operators can then claim rewards later by visiting the same cluster details page. +3. Internally, after clicking `Claim All` or `Distribute All`, the split wallet sends the funds to the Split Main contract. +4. The Split Main then sends proportional rewards to **address A**, completing steps 2a, 3, and 4 with a single click. +5. Other addresses (e.g., B, C, D) can later click on `Claim All` to receive their share of the rewards. + +### Launchpad Edge Cases {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: The `Claimable` column doesn’t match the amount next to the `Claim All` button. {#case-1-the-claimable-column-doesnt-match-the-amount-next-to-the-claim-all-button} +![](/img/gitbook/image-87.png) + +![](/img/gitbook/image-1-1-1-1-1.png) + +In this scenario, someone else (a splitter or non-splitter address) has already distributed rewards to the Split Main (e.g., 0.12 ETH). However, your validators (4 in this case) have earned an additional 0.2 ETH in rewards. Your total effective claimable balance is 0.032 ETH, which you can claim using the `Claim All` button. + +:::info +Your total effective claimable amount will always be displayed next to the `Claim All` button. +::: + +#### Case 2: You don't see a `Claim All` button but instead see `Distribute All`. {#case-2-you-dont-see-a-claim-all-button-but-instead-see-distribute-all} +![](/img/gitbook/image-88.png) + +This happens because the connected address is not listed in the split configuration. You may have used a different operator address from the one in the splitter configuration. You can: + +* Distribute all rewards using the connected address for all operators and claim using your address in the splitter configuration. +* Switch to the splitter address and claim directly. + +Note: It costs the same gas to distribute rewards for one address as it does for all addresses. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows a `Claim All` amount. {#case-3-you-just-created-a-new-cluster-with-no-active-validators-or-rewards-but-it-shows-a-claim-all} +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all `Claim All` buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.8/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.8/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..ff63cdf1dc --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,933 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction {#introduction} +Users looking to exit staking entirely and withdraw their full balance back must sign and broadcast a "voluntary exit" message with validator keys which will start the process of exiting from staking. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proportion of principal and rewards. + +There are two ways to sign the partial exit and broadcast the full exit. Both the solutions don't require gas. + +1. **Using the Charon’s exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via launchpad and ability to download partial exits and broadcast them later as required. Users don’t have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use launchpad to monitor exit status and will have to use grafana to query the partial exit status. + +:::info +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +As per your preferences, choose the correct combination of - + +1. **Network** : Mainnet or Hoodi +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quanity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +#### Step 1: Submit partial exit {#introduction} + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message.\\ + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=hoodi \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=hoodi \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\ + \\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2.\ + \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3.\ + \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: \\ + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=hoodi \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=hoodi \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network hoodi \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network hoodi \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1.\\ + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. \\ + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. \\ + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](https://docs.obol.org/img/PartialExitsStatus.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +#### Exit a distributed validator using DappNode + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.8/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.8/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..125a356201 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/running/monitoring.md @@ -0,0 +1,89 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/charonoverview/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show following page. Choose Discord in the `Integration` drop down.\\ + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md). + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.8/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.8/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..f6c647054d --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,124 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +#### Pull latest changes to the repo {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +#### Conflicts {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +#### Pull latest changes to the repo {#pull-latest-changes-to-the-repo} +```sh +git pull +``` + +#### Create (or recreate) your DV stack {#create-or-recreate-your-dv-stack} +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +#### Conflicts {#conflicts} +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + diff --git a/versioned_docs/version-v1.8/run-a-dv/start/README.md b/versioned_docs/version-v1.8/run-a-dv/start/README.md new file mode 100644 index 0000000000..f8e137e70b --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# start + diff --git a/versioned_docs/version-v1.8/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.8/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..6859d75867 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,201 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](../../learn/intro/key-concepts.md#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](create-a-dv-with-a-group.mdx) instead for this latter case. +::: + +### Pre-requisites {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the [DV Launchpad](../../learn/intro/launchpad.md) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.8.0 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](../../learn/charon/charon-cli-reference.md#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 create cluster \ + --nodes=6 \ + --network=hoodi \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead \ + --publish +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](../../learn/intro/launchpad.md), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately.\ +\ +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Hoodi testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Set up the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](../../learn/charon/charon-cli-reference.md) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample .env +``` +::: + + diff --git a/versioned_docs/version-v1.8/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.8/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..b006e02751 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,604 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](../prepare/deployment-best-practices.md#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](../../advanced-and-troubleshooting/troubleshooting/errors.md#how-to-fix-permission-denied-errors) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client** + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package** + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge** + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful** + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +**Collect addresses, configure the cluster, share the invitation** + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](../../learn/intro/launchpad.md) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](../../learn/intro/launchpad.md#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + 1. Select the desired amount of validators (32 ETH each) the cluster will run. (Note that the mainnet launchpad is restricted to one validator for now.) + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](#step-1-get-your-enr) in the "What is your charon client's ENR?" field. + 3. Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. + 4. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions of participating as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +**Join the cluster prepared by the creator** + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address provided to the leader.\\ + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue.\\ + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](#step-1-get-your-enr).\\ + + ![](/img/gitbook/image-83.png) +6. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +7. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](../../learn/charon/dkg.md) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) \\ + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. \\ + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.8.0 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run.\\ + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page.\\ + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +**Create a DV Node Backup** + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present.\\ + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long-term. + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose, further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Hoodi testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +```sh +# To prepare the node for the Hoodi test network +# Copy ".env.sample.hoodi", renaming it ".env" +cp .env.sample.hoodi .env + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env +``` + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```sh + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +``` + +:::danger +Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. +::: + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/charonoverview/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). + + + + +:::danger +Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. +::: + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Stop your docker compose + +```sh +docker compose down +``` + +2. Uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +3. Uncomment `EL=el-none` and `CL=cl-none` variables in the `.env` file and comment `EL=el-nethermind` and `CL=cl-lighthouse` variables: + +```sh +... +#EL=el-nethermind +... +EL=el-none +... +#CL=cl-lighthouse +... +CL=cl-none +... +``` + +4. Start your docker compose + +```sh +docker compose up -d +``` + + + + +To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate** + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Hoodi network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=hoodi --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key** + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ hoodi teku +``` + +**Sedge Run** + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. + + + +Use an Ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. + + + +Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. + + + +Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. + + + +:::tip +In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is `:3610`. Read more about Charon's networking [here](../../learn/charon/charon-networking.md). +::: + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](../running/activate-a-dv.md) to begin staking. diff --git a/versioned_docs/version-v1.8/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.8/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..8f94306da6 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,77 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics to Obol Monitoring" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics to Obol Monitoring + +:::info +This is **optional** and does not confer any special privileges within the Obol Network. +::: + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](http://docs.obol.org/run-a-dv/start/quickstart_overview), and have been provided with **Monitoring Credentials** used to push distributed validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve your Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +#### Update the monitoring token in the `.env` file + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +#### Save the `.env` file and restart Prometheus + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab.\\ + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it.\\ + + ![](/img/gitbook/image-86.png) + + + +Get a Prometheus monitoring credential from the Obol core team, it will look like: + +```log +obol20tnt8UC... +``` + +Then, either add `--set centralMonitoring.enabled=true --set-string centralMonitoring.token='YOUR_TOKEN_HERE'` to your `helm install` command, or if using a Values.yaml file, update `centralMonitoring.enabled` to `true`, and `centralMonitoring.token` to the monitoring credential you have been given, and then install/upgrade the chart. + +```yaml +# -- Central Monitoring +centralMonitoring: + # -- Specifies whether central monitoring should be enabled + enabled: true + # -- https endpoint to obol central prometheus + promEndpoint: "https://vm.monitoring.gcp.obol.tech/write" + # -- The authentication token to the central Obol prometheus instance + token: "YOUR_TOKEN_HERE" +``` + + diff --git a/versioned_docs/version-v1.8/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.8/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..371dc03d45 --- /dev/null +++ b/versioned_docs/version-v1.8/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to utilise Distributed Validators for solo or multi-operator staking. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](./create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](./create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.8/sdk/classes/Client.md b/versioned_docs/version-v1.8/sdk/classes/Client.md new file mode 100644 index 0000000000..f14400d164 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/classes/Client.md @@ -0,0 +1,302 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Defined in: [index.ts:67](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L67) + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +## Extends + +- `Base` + +## Constructors + +### Constructor + +> **new Client**(`config`, `signer?`, `provider?`): `Client` + +Defined in: [index.ts:113](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L113) + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `config` | \{ `baseUrl?`: `string`; `chainId?`: `number`; \} | Client configurations | +| `config.baseUrl?` | `string` | obol-api url | +| `config.chainId?` | `number` | Blockchain network ID | +| `signer?` | [`SignerType`](../type-aliases/SignerType.md) | ethersJS Signer | +| `provider?` | [`ProviderType`](../type-aliases/ProviderType.md) | - | + +#### Returns + +`Client` + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +#### Overrides + +`Base.constructor` + +## Properties + +| Property | Modifier | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `incentives` | `public` | [`Incentives`](Incentives.md) | The incentives module, responsible for managing Obol tokens distribution. | [index.ts:77](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L77) | +| `exit` | `public` | [`Exit`](Exit.md) | The exit module, responsible for managing exit validation. | [index.ts:83](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L83) | +| `splits` | `public` | [`ObolSplits`](ObolSplits.md) | The splits module, responsible for managing splits. | [index.ts:89](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L89) | +| `eoa` | `public` | [`EOA`](EOA.md) | The eoa module, responsible for managing EOA operations. | [index.ts:95](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L95) | +| `provider` | `public` | [`ProviderType`](../type-aliases/ProviderType.md) \| `null` \| `undefined` | The blockchain provider, used to interact with the network. It can be null, undefined, or a valid provider instance and defaults to the Signer provider if Signer is passed. | [index.ts:101](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L101) | + +## Methods + +### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`\<`string`\> + +Defined in: [index.ts:143](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L143) + +Accepts Obol terms and conditions to be able to create or update data. + +#### Returns + +`Promise`\<`string`\> + +terms and conditions acceptance success message. + +#### Throws + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions: +[acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +*** + +### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +Defined in: [index.ts:198](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L198) + +Deploys OWR and Splitter Proxy. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +#### Returns + +`Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit: +[createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +*** + +### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +Defined in: [index.ts:325](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L325) + +Deploys Splitter Proxy. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +#### Returns + +`Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit: +[createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +*** + +### getOWRTranches() + +> **getOWRTranches**(`owrAddress`): `Promise`\<[`OWRTranches`](../type-aliases/OWRTranches.md)\> + +Defined in: [index.ts:430](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L430) + +Read OWR Tranches. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `owrAddress` | `string` | Address of the Deployed OWR Contract | + +#### Returns + +`Promise`\<[`OWRTranches`](../type-aliases/OWRTranches.md)\> + +owr tranch information about principal and reward reciepient, as well as the principal amount + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +*** + +### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`\<`string`\> + +Defined in: [index.ts:448](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L448) + +Creates a cluster definition which contains cluster configuration. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +#### Returns + +`Promise`\<`string`\> + +config_hash. + +#### Throws + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition: +[createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +*** + +### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`\<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)\> + +Defined in: [index.ts:513](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L513) + +Approves joining a cluster with specific configuration. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +#### Returns + +`Promise`\<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)\> + +The cluster definition. + +#### Throws + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition: +[acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +*** + +### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`\<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)\> + +Defined in: [index.ts:570](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L570) + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +#### Returns + +`Promise`\<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)\> + +The cluster definition for config hash + +#### Throws + +On not found config hash. + +An example of how to use getClusterDefinition: +[getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +*** + +### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`\<[`ClusterLock`](../type-aliases/ClusterLock.md)\> + +Defined in: [index.ts:589](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L589) + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `configHash` | `string` | The configuration hash in cluster-definition | + +#### Returns + +`Promise`\<[`ClusterLock`](../type-aliases/ClusterLock.md)\> + +The matched cluster details (lock) from DB + +#### Throws + +On not found cluster definition or lock. + +An example of how to use getClusterLock: +[getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +*** + +### getClusterLockByHash() + +> **getClusterLockByHash**(`lockHash`): `Promise`\<[`ClusterLock`](../type-aliases/ClusterLock.md)\> + +Defined in: [index.ts:605](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L605) + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `lockHash` | `string` | The configuration hash in cluster-definition | + +#### Returns + +`Promise`\<[`ClusterLock`](../type-aliases/ClusterLock.md)\> + +The matched cluster details (lock) from DB + +#### Throws + +On not found cluster definition or lock. diff --git a/versioned_docs/version-v1.8/sdk/classes/EOA.md b/versioned_docs/version-v1.8/sdk/classes/EOA.md new file mode 100644 index 0000000000..7f12a5ddec --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/classes/EOA.md @@ -0,0 +1,117 @@ +--- +sidebar_label: "EOA" +slug: /sdk/classes/eoa +unlisted: true +--- + +# EOA + +Defined in: [eoa/eoa.ts:26](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/eoa/eoa.ts#L26) + +**`Internal`** + +EOA can be used for managing EOA (Externally Owned Account) operations like withdrawals. + + Access it through Client.eoa. + +## Example + +```ts +const obolClient = new Client(config); +await obolClient.eoa.requestWithdrawal(EOAWithdrawalPayload); +``` + +## Methods + +### requestWithdrawal() + +> **requestWithdrawal**(`payload`): `Promise`\<\{ `txHash`: `string` \| `null`; \}\> + +Defined in: [eoa/eoa.ts:65](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/eoa/eoa.ts#L65) + +Requests withdrawal from an EOA contract. + +This method allows requesting withdrawal of validator funds. +The withdrawal request includes validator public key and corresponding withdrawal amount. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`EOAWithdrawalPayload`](../type-aliases/EOAWithdrawalPayload.md) | Data needed to request withdrawal | + +#### Returns + +`Promise`\<\{ `txHash`: `string` \| `null`; \}\> + +Transaction hash of the withdrawal request + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the signer is not provided or the request fails + +An example of how to use requestWithdrawal: +```typescript +const result = await client.eoa.requestWithdrawal({ + pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + allocation: 32, // 32 ETH + requiredFee: '1' // in wei +}); +console.log('Withdrawal requested:', result.txHash); +``` + +*** + +### deposit() + +> **deposit**(`payload`): `Promise`\<\{ `txHashes`: `string`[]; \}\> + +Defined in: [eoa/eoa.ts:132](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/eoa/eoa.ts#L132) + +Deposits to batch deposit contract. + +This method allows depositing multiple validators to the Ethereum beacon chain +using the Pier Two batch deposit contract for gas efficiency. +Each deposit includes validator public key, withdrawal credentials, signature, and amount. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`EOADepositPayload`](../type-aliases/EOADepositPayload.md) | Data needed to deposit to batch contract | + +#### Returns + +`Promise`\<\{ `txHashes`: `string`[]; \}\> + +Array of transaction hashes for all batches + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +**⚠️ Gas Limit:** Due to EVM constraints, it is recommended to deposit in batches of up to 500 at a time. + +#### Throws + +Will throw an error if the signer is not provided, contract is not configured, or the deposit fails + +An example of how to use deposit: +```typescript +const result = await client.eoa.deposit({ + deposits: [{ + pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + withdrawal_credentials: '0x1234567890123456789012345678901234567890', + deposit_data_root: '0x1234567890123456789012345678901234567890123456789012345678901234', + signature: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + amount: '32000000000000000000' // 32 ETH in wei + }] +}); +console.log('Deposits completed:', result.txHashes); +``` diff --git a/versioned_docs/version-v1.8/sdk/classes/Exit.md b/versioned_docs/version-v1.8/sdk/classes/Exit.md new file mode 100644 index 0000000000..7966ebac54 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/classes/Exit.md @@ -0,0 +1,310 @@ +--- +sidebar_label: "Exit" +slug: /sdk/classes/exit +unlisted: true +--- + +# Exit + +Defined in: [exits/exit.ts:85](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L85) + +Exit validation and verification class for Obol distributed validators. + +This class provides functionality to validate and verify voluntary exit signatures +for distributed validators in an Obol cluster. It handles both partial exit signatures +from individual operators and payload signatures that authorize exit operations. + +The class supports: +- Verification of BLS signatures for partial exit messages +- Verification of ECDSA signatures for exit payload authorization +- Validation of exit blobs against cluster configuration +- Duplicate detection and epoch validation + +## Example + +```typescript +const exit = new Exit(1, provider); // Mainnet with provider + +// Verify a partial exit signature +const isValid = await exit.verifyPartialExitSignature( + publicShareKey, + signedExitMessage, + forkVersion, + genesisValidatorsRoot +); + +// Validate exit blobs for a cluster +const validBlobs = await exit.validateExitBlobs( + clusterConfig, + exitsPayload, + beaconNodeApiUrl, + existingBlobData +); +``` + +## Constructors + +### Constructor + +> **new Exit**(`chainId`, `provider`): `Exit` + +Defined in: [exits/exit.ts:104](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L104) + +Creates a new Exit instance for validator exit operations. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `chainId` | `number` | The Ethereum chain ID (e.g., 1 for mainnet, 5 for goerli) | +| `provider` | [`ProviderType`](../type-aliases/ProviderType.md) \| `null` \| `undefined` | Optional Ethereum provider for blockchain interactions | + +#### Returns + +`Exit` + +#### Example + +```typescript +// For mainnet with a provider +const exit = new Exit(1, provider); + +// For goerli testnet without provider +const exit = new Exit(5, null); +``` + +## Methods + +### verifyPartialExitSignature() + +> **verifyPartialExitSignature**(`publicShareKey`, `signedExitMessage`, `forkVersion`, `genesisValidatorsRootString`): `Promise`\<`boolean`\> + +Defined in: [exits/exit.ts:192](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L192) + +Verifies a partial exit signature from a distributed validator operator. + +This method validates that a partial exit signature was correctly signed by the +operator's share of the distributed validator's private key. It performs BLS +signature verification using the appropriate fork version and genesis validators root. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `publicShareKey` | `string` | The operator's public share key (BLS public key, hex string with or without 0x prefix) | +| `signedExitMessage` | [`SignedExitValidationMessage`](../interfaces/SignedExitValidationMessage.md) | The signed exit message containing the exit details and signature | +| `forkVersion` | `string` | The Ethereum fork version (e.g., "0x00000000" for mainnet) | +| `genesisValidatorsRootString` | `string` | The genesis validators root for the network (hex string) | + +#### Returns + +`Promise`\<`boolean`\> + +Promise resolving to true if the signature is valid, false otherwise + +#### Throws + +When unable to determine the Capella fork version for the given network + +#### Throws + +When BLS library initialization or verification fails + +#### Example + +```typescript +const isValid = await exit.verifyPartialExitSignature( + "0x1234...abcd", // operator's public share key + { + message: { epoch: "12345", validator_index: "67890" }, + signature: "0xabcd...1234" + }, + "0x00000000", // mainnet fork version + "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95" +); +``` + +*** + +### verifyExitPayloadSignature() + +> **verifyExitPayloadSignature**(`enrString`, `exitsPayload`): `Promise`\<`boolean`\> + +Defined in: [exits/exit.ts:256](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L256) + +Verifies the exit payload signature using the operator's ENR. + +This method validates that an exit payload was signed by the correct operator +using ECDSA signature verification. The signature is verified against the +operator's public key extracted from their ENR (Ethereum Node Record). + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `enrString` | `string` | The operator's ENR string containing their identity and public key | +| `exitsPayload` | [`ExitValidationPayload`](../interfaces/ExitValidationPayload.md) | The exit validation payload containing partial exits and operator signature | + +#### Returns + +`Promise`\<`boolean`\> + +Promise resolving to true if the payload signature is valid, false otherwise + +#### Throws + +When the ENR string is invalid or cannot be decoded + +#### Throws + +When the signature format is invalid (must be 130 hex characters) + +#### Throws + +When signature verification encounters an error + +#### Example + +```typescript +const isValid = await exit.verifyExitPayloadSignature( + "enr:-LK4QFo_n0dUm4PKejSOXf8JkSWq5EINV0XhG1zY00d...", // operator ENR + { + partial_exits: [exitBlob1, exitBlob2], + share_idx: 1, + signature: "0x1234...abcd" // ECDSA signature (130 hex chars) + } +); +``` + +*** + +### validateExitBlobs() + +> **validateExitBlobs**(`clusterConfig`, `exitsPayload`, `beaconNodeApiUrl`, `existingBlobData`): `Promise`\<[`ExitValidationBlob`](../interfaces/ExitValidationBlob.md)[]\> + +Defined in: [exits/exit.ts:533](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L533) + +Validates exit blobs against cluster configuration and existing data. + +This method performs comprehensive validation of exit blobs including: +- Operator authorization and payload signature verification +- Network parameter validation (genesis root, fork version) +- Public key validation against cluster configuration +- Partial signature verification for each exit blob +- Duplicate detection and epoch progression validation +- Signature consistency checks for existing exits + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `clusterConfig` | [`ExitClusterConfig`](../interfaces/ExitClusterConfig.md) | The cluster configuration containing operators and distributed validators | +| `exitsPayload` | [`ExitValidationPayload`](../interfaces/ExitValidationPayload.md) | The exit validation payload with partial exits and operator info | +| `beaconNodeApiUrl` | `string` | The beacon node API URL for network parameter retrieval | +| `existingBlobData` | [`ExistingExitValidationBlobData`](../interfaces/ExistingExitValidationBlobData.md) \| `null` | Existing exit blob data for duplicate detection, or null if none exists | + +#### Returns + +`Promise`\<[`ExitValidationBlob`](../interfaces/ExitValidationBlob.md)[]\> + +Promise resolving to an array of validated, non-duplicate exit blobs + +#### Throws + +When share_idx is invalid or out of bounds for the cluster operators + +#### Throws + +When payload signature verification fails + +#### Throws + +When network parameters cannot be retrieved or are invalid + +#### Throws + +When a public key is not found in the cluster's distributed validators + +#### Throws + +When a partial exit signature is invalid + +#### Throws + +When exit epoch validation fails (new epoch not greater than existing) + +#### Throws + +When validator index mismatches with existing data + +#### Throws + +When signature mismatches for the same epoch and operator + +#### Example + +```typescript +const validExitBlobs = await exit.validateExitBlobs( + { + definition: { + operators: [{ enr: "enr:-LK4Q..." }], + fork_version: "0x00000000", + threshold: 1 + }, + distributed_validators: [{ + distributed_public_key: "0x1234...abcd", + public_shares: ["0x5678...efgh"] + }] + }, + { + partial_exits: [exitBlob], + share_idx: 1, + signature: "0x1234...abcd" + }, + "http://localhost:5052", + existingBlobData // or null for new exits +); +``` + +*** + +### recombineExitBlobs() + +> **recombineExitBlobs**(`exitBlob`): `Promise`\<`FullExitBlob`\> + +Defined in: [exits/exit.ts:585](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L585) + +Recombines exit blobs into a single exit blob. + +This method aggregates partial exit signatures from multiple operators into a single exit blob. +It ensures that the signatures are properly ordered and aggregated according to the operator indices. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `exitBlob` | [`ExistingExitValidationBlobData`](../interfaces/ExistingExitValidationBlobData.md) | The existing exit blob data containing partial exit signatures | + +#### Returns + +`Promise`\<`FullExitBlob`\> + +Promise resolving to a single exit blob with aggregated signatures + +#### Throws + +When no valid signatures are found for aggregation + +#### Throws + +When signature length is invalid + +#### Throws + +When signature parsing fails + +#### Example + +```typescript +const aggregatedExitBlob = await exit.recombineExitBlobs(existingBlobData); +``` diff --git a/versioned_docs/version-v1.8/sdk/classes/Incentives.md b/versioned_docs/version-v1.8/sdk/classes/Incentives.md new file mode 100644 index 0000000000..e783194cb9 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/classes/Incentives.md @@ -0,0 +1,114 @@ +--- +sidebar_label: "Incentives" +slug: /sdk/classes/incentives +unlisted: true +--- + +# Incentives + +Defined in: [incentives/incentives.ts:24](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L24) + +**`Internal`** + +Incentives can be used for fetching and claiming Obol incentives. + + Access it through Client.incentives. + +## Example + +```ts +const obolClient = new Client(config); +await obolClient.incentives.claimIncentives(address); +``` + +## Methods + +### claimIncentives() + +> **claimIncentives**(`address`): `Promise`\<[`ClaimIncentivesResponse`](../type-aliases/ClaimIncentivesResponse.md)\> + +Defined in: [incentives/incentives.ts:65](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L65) + +Claims Obol incentives from a Merkle Distributor contract using an address. + +This method automatically fetches incentive data and verifies whether the incentives have already been claimed. +If `txHash` is `null`, it indicates that the incentives were already claimed. + +Note: This method is not yet enabled and will throw an error if called. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `address` | `string` | The address to claim incentives for | + +#### Returns + +`Promise`\<[`ClaimIncentivesResponse`](../type-aliases/ClaimIncentivesResponse.md)\> + +The transaction hash or already claimed status + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the incentives data is not found or the claim fails + +An example of how to use claimIncentives: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L281) + +*** + +### isClaimed() + +> **isClaimed**(`contractAddress`, `index`): `Promise`\<`boolean`\> + +Defined in: [incentives/incentives.ts:124](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L124) + +Read isClaimed. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `contractAddress` | `string` | Address of the Merkle Distributor Contract | +| `index` | `number` | operator index in merkle tree | + +#### Returns + +`Promise`\<`boolean`\> + +true if incentives are already claime + +An example of how to use isClaimed: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L266) + +*** + +### getIncentivesByAddress() + +> **getIncentivesByAddress**(`address`): `Promise`\<[`ClaimableIncentives`](../type-aliases/ClaimableIncentives.md)\> + +Defined in: [incentives/incentives.ts:143](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L143) + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `address` | `string` | Operator address | + +#### Returns + +`Promise`\<[`ClaimableIncentives`](../type-aliases/ClaimableIncentives.md)\> + +The matched incentives from DB + +#### Throws + +On not found if address not found. + +An example of how to use getIncentivesByAddress: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L250) diff --git a/versioned_docs/version-v1.8/sdk/classes/ObolSplits.md b/versioned_docs/version-v1.8/sdk/classes/ObolSplits.md new file mode 100644 index 0000000000..529d51d206 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/classes/ObolSplits.md @@ -0,0 +1,194 @@ +--- +sidebar_label: "ObolSplits" +slug: /sdk/classes/obolsplits +unlisted: true +--- + +# ObolSplits + +Defined in: [splits/splits.ts:42](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L42) + +**`Internal`** + +ObolSplits can be used for creating and managing Obol splits. + + Access it through Client.splits. + +## Example + +```ts +const obolClient = new Client(config); +await obolClient.splits.createValidatorManagerAndRewardsSplit(OVMRewardsSplitPayload); +``` + +## Methods + +### createValidatorManagerAndRewardsSplit() + +> **createValidatorManagerAndRewardsSplit**(`payload`): `Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +Defined in: [splits/splits.ts:76](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L76) + +Creates an Obol OVM and Pull split configuration for rewards-only scenario. + +This method deploys OVM and SplitV2 contracts for managing validator rewards only. +Principal is handled by a single address, while rewards are split among recipients. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMRewardsSplitPayload`](../type-aliases/OVMRewardsSplitPayload.md) | Data needed to deploy OVM and SplitV2 | + +#### Returns + +`Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +OVM address as withdrawal address and splitter as fee recipient + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +**📌 Note:** The Obol Validator Manager (OVM) feature is only enabled on Hoodi on launchpad. + +#### Throws + +Will throw an error if the splitter configuration is not supported or deployment fails + +An example of how to use createValidatorManagerAndRewardsSplit: +[createValidatorManagerAndRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L333) + +*** + +### createValidatorManagerAndTotalSplit() + +> **createValidatorManagerAndTotalSplit**(`payload`): `Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +Defined in: [splits/splits.ts:244](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L244) + +Creates an Obol OVM and Total split configuration for total split scenario. + +This method deploys OVM and SplitV2 contracts for managing both validator rewards and principal. +Both rewards and principal are split among recipients, with rewards including RAF recipient. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMTotalSplitPayload`](../type-aliases/OVMTotalSplitPayload.md) | Data needed to deploy OVM and SplitV2 | + +#### Returns + +`Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +OVM address as withdrawal address and splitter as fee recipient + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +**📌 Note:** The Obol Validator Manager (OVM) feature is only enabled on Hoodi on launchpad. + +#### Throws + +Will throw an error if the splitter configuration is not supported or deployment fails + +An example of how to use createValidatorManagerAndTotalSplit: +[createValidatorManagerAndTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#340) + +*** + +### requestWithdrawal() + +> **requestWithdrawal**(`payload`): `Promise`\<\{ `txHash`: `string`; \}\> + +Defined in: [splits/splits.ts:442](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L442) + +Requests withdrawal from an OVM contract. + +This method allows requesting withdrawal of validator funds from an OVM contract. +The withdrawal request includes OVM address, validator public keys and corresponding withdrawal amounts. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMRequestWithdrawalPayload`](../type-aliases/OVMRequestWithdrawalPayload.md) | Data needed to request withdrawal | + +#### Returns + +`Promise`\<\{ `txHash`: `string`; \}\> + +Transaction hash of the withdrawal request + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the signer is not provided, OVM address is invalid, or the request fails + +An example of how to use requestWithdrawal: +```typescript +const result = await client.splits.requestWithdrawal({ + ovmAddress: '0x1234567890123456789012345678901234567890', + pubKeys: ['0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456'], + amounts: ['32000000000'], // 32 ETH in gwei + withdrawalFees: '1000000000000000' // Total fees in wei +}); +console.log('Withdrawal requested:', result.txHash); +``` + +*** + +### deposit() + +> **deposit**(`payload`): `Promise`\<\{ `txHashes`: `string`[]; \}\> + +Defined in: [splits/splits.ts:492](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L492) + +Deposits to OVM contract by sending individual transactions for each deposit. + +This method allows depositing to an OVM contract. Each deposit is sent as a separate transaction +Each deposit includes validator public key, withdrawal credentials, signature, deposit data root, and amount. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMDepositPayload`](../type-aliases/OVMDepositPayload.md) | Data needed to deposit to OVM | + +#### Returns + +`Promise`\<\{ `txHashes`: `string`[]; \}\> + +Array of transaction hashes, one for each deposit + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the signer is not provided, OVM address is invalid, or the deposit fails + +An example of how to use deposit: +```typescript +const result = await client.splits.deposit({ + ovmAddress: '0x1234567890123456789012345678901234567890', + deposits: [{ + pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + withdrawal_credentials: '0x1234567890123456789012345678901234567890', + signature: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + deposit_data_root: '0x1234567890123456789012345678901234567890123456789012345678901234', + amount: '32000000000000000000' // 32 ETH in wei + }] +}); +console.log('Deposits completed:', result.txHashes); +``` diff --git a/versioned_docs/version-v1.8/sdk/classes/README.md b/versioned_docs/version-v1.8/sdk/classes/README.md new file mode 100644 index 0000000000..2c00796913 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# Classes + diff --git a/versioned_docs/version-v1.8/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.8/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..89613c3379 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +# FORK\_MAPPING + +Defined in: [types.ts:13](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L13) + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `0x00000000` | `1` | Mainnet. | [types.ts:15](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L15) | +| `0x00001020` | `5` | Goerli/Prater. | [types.ts:18](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L18) | +| `0x00000064` | `100` | Gnosis Chain. | [types.ts:21](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L21) | +| `0x01017000` | `17000` | Holesky. | [types.ts:24](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L24) | +| `0x90000069` | `11155111` | Sepolia. | [types.ts:27](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L27) | +| `0x10000910` | `560048` | Hoodi Chain. | [types.ts:30](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L30) | diff --git a/versioned_docs/version-v1.8/sdk/enumerations/README.md b/versioned_docs/version-v1.8/sdk/enumerations/README.md new file mode 100644 index 0000000000..c5e9c93aa7 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# Enumerations + diff --git a/versioned_docs/version-v1.8/sdk/functions/README.md b/versioned_docs/version-v1.8/sdk/functions/README.md new file mode 100644 index 0000000000..082855458f --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# Functions + diff --git a/versioned_docs/version-v1.8/sdk/functions/clusterConfigOrDefinitionHash.md b/versioned_docs/version-v1.8/sdk/functions/clusterConfigOrDefinitionHash.md new file mode 100644 index 0000000000..a45a6f0718 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/functions/clusterConfigOrDefinitionHash.md @@ -0,0 +1,24 @@ +--- +sidebar_label: "clusterConfigOrDefinitionHash()" +slug: /sdk/functions/clusterconfigordefinitionhash +unlisted: true +--- + +# clusterConfigOrDefinitionHash() + +> **clusterConfigOrDefinitionHash**(`cluster`, `configOnly`): `string` + +Defined in: [verification/common.ts:64](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L64) + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `cluster` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster configuration or the cluster definition | +| `configOnly` | `boolean` | a boolean to indicate config hash or definition hash | + +## Returns + +`string` + +The config hash or the definition hash in of the corresponding cluster diff --git a/versioned_docs/version-v1.8/sdk/functions/clusterLockHash.md b/versioned_docs/version-v1.8/sdk/functions/clusterLockHash.md new file mode 100644 index 0000000000..bd6893e8fd --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/functions/clusterLockHash.md @@ -0,0 +1,25 @@ +--- +sidebar_label: "clusterLockHash()" +slug: /sdk/functions/clusterlockhash +unlisted: true +--- + +# clusterLockHash() + +> **clusterLockHash**(`clusterLock`): `string` + +Defined in: [verification/common.ts:116](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L116) + +Returns the SSZ cluster lock hash of the given cluster lock object + +## Parameters + +| Parameter | Type | +| ------ | ------ | +| `clusterLock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | + +## Returns + +`string` + +The cluster lock hash in of the corresponding cluster lock diff --git a/versioned_docs/version-v1.8/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.8/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..01c038e7d0 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/functions/validateClusterLock.md @@ -0,0 +1,32 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock() + +> **validateClusterLock**(`lock`, `safeRpcUrl?`): `Promise`\<`boolean`\> + +Defined in: [services.ts:14](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/services.ts#L14) + +Verifies Cluster Lock's validity. + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | +| `safeRpcUrl?` | `string` | optional safeRpcUrl for safe wallet verification | + +## Returns + +`Promise`\<`boolean`\> + +boolean result to indicate if lock is valid + +## Throws + +on missing keys or values. + +An example of how to use validateClusterLock: +[validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) diff --git a/versioned_docs/version-v1.8/sdk/functions/verifyDepositData.md b/versioned_docs/version-v1.8/sdk/functions/verifyDepositData.md new file mode 100644 index 0000000000..bd9fa10451 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/functions/verifyDepositData.md @@ -0,0 +1,34 @@ +--- +sidebar_label: "verifyDepositData()" +slug: /sdk/functions/verifydepositdata +unlisted: true +--- + +# verifyDepositData() + +> **verifyDepositData**(`distributedPublicKey`, `depositData`, `withdrawalAddress`, `forkVersion`, `compounding?`): `object` + +Defined in: [verification/common.ts:362](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L362) + +Verify deposit data withdrawal credintials and signature + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `distributedPublicKey` | `string` | - | +| `depositData` | `Partial`\<[`DepositData`](../type-aliases/DepositData.md)\> | - | +| `withdrawalAddress` | `string` | withdrawal address in definition file. | +| `forkVersion` | `string` | fork version in definition file. | +| `compounding?` | `boolean` | - | + +## Returns + +`object` + +- return if deposit data is valid. + +| Name | Type | Defined in | +| ------ | ------ | ------ | +| `isValidDepositData` | `boolean` | [verification/common.ts:368](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L368) | +| `depositDataMsg` | `Uint8Array` | [verification/common.ts:368](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L368) | diff --git a/versioned_docs/version-v1.8/sdk/index.md b/versioned_docs/version-v1.8/sdk/index.md new file mode 100644 index 0000000000..6becff5bfc --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/index.md @@ -0,0 +1,166 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + +# Intro + +**SDK Version:** v2.11.8 + +![Obol Logo](https://obol.org/obolnetwork.png) + +## Obol SDK + +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](../api/what-is-this-api.md). + +## Getting Started + +Checkout our [docs](../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +### Terms and Conditions + +## Terms and Conditions +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +## ⚠️ Important Security Notice: +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +- The private key is securely stored (e.g., in an `.env` file). +- Never commit or push your `.env` file containing the private key to version control. + +## ⚡️ Integration with Safe Wallet + +When integrating the Obol SDK with a **Safe Wallet**, you can either pass an RPC URL OR provide the `RPC_MAINNET` or `RPC_HOLESKY` or `RPC_GNOSIS` or `RPC_SEPOLIA` or `RPC_HOODI` environment variable, pointing to the correct network's RPC URL. This is required to interact with Safe kit. + +## Contributing + +Please review the following guidelines: + +- [How to Report Bugs](#how-to-report-bugs) +- [How to Propose Changes](#how-to-propose-changes) +- [Code Review Process](#code-review-process) + +### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +## Next.js / SSR Configuration + +If using this SDK in **Next.js** or other SSR frameworks, add this minimal config to your `next.config.js`: + +```javascript +webpack: (config, { isServer, webpack }) => { + if (!isServer) { + config.plugins.push( + new webpack.DefinePlugin({ + 'process.stdout.isTTY': 'false', + 'process.stderr.isTTY': 'false', + }) + ); + } else { + // Server: Externalize native dependencies + config.externals = config.externals || []; + config.externals.push({ + '@chainsafe/bls': 'commonjs @chainsafe/bls', + '@chainsafe/blst': 'commonjs @chainsafe/blst', + 'bcrypto': 'commonjs bcrypto', + }); + } + + // Ignore .node files + config.plugins.push( + new webpack.IgnorePlugin({ resourceRegExp: /\.node$/ }) + ); + + return config; +} +``` + +## Enumerations + +- [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +## Classes + +- [EOA](classes/EOA.md) +- [Exit](classes/Exit.md) +- [Incentives](classes/Incentives.md) +- [Client](classes/Client.md) +- [ObolSplits](classes/ObolSplits.md) + +## Interfaces + +- [ClusterDefinition](interfaces/ClusterDefinition.md) +- [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) +- [ExitOperator](interfaces/ExitOperator.md) +- [ExitClusterDefinition](interfaces/ExitClusterDefinition.md) +- [ExitDistributedValidator](interfaces/ExitDistributedValidator.md) +- [ExitClusterConfig](interfaces/ExitClusterConfig.md) +- [ExitValidationMessage](interfaces/ExitValidationMessage.md) +- [SignedExitValidationMessage](interfaces/SignedExitValidationMessage.md) +- [ExitValidationBlob](interfaces/ExitValidationBlob.md) +- [ExitValidationPayload](interfaces/ExitValidationPayload.md) +- [ExistingExitValidationBlobData](interfaces/ExistingExitValidationBlobData.md) + +## Type Aliases + +- [ClusterOperator](type-aliases/ClusterOperator.md) +- [OperatorPayload](type-aliases/OperatorPayload.md) +- [ClusterCreator](type-aliases/ClusterCreator.md) +- [ClusterValidator](type-aliases/ClusterValidator.md) +- [ClusterPayload](type-aliases/ClusterPayload.md) +- [SplitRecipient](type-aliases/SplitRecipient.md) +- [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +- [OVMBaseSplitPayload](type-aliases/OVMBaseSplitPayload.md) +- [OVMRewardsSplitPayload](type-aliases/OVMRewardsSplitPayload.md) +- [OVMTotalSplitPayload](type-aliases/OVMTotalSplitPayload.md) +- [OVMSplitPayload](type-aliases/OVMSplitPayload.md) +- [SplitV2Recipient](type-aliases/SplitV2Recipient.md) +- [OWRTranches](type-aliases/OWRTranches.md) +- [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +- [BuilderRegistration](type-aliases/BuilderRegistration.md) +- [DepositData](type-aliases/DepositData.md) +- [DistributedValidator](type-aliases/DistributedValidator.md) +- [ClusterLock](type-aliases/ClusterLock.md) +- [ClaimableIncentives](type-aliases/ClaimableIncentives.md) +- [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) +- [ProviderType](type-aliases/ProviderType.md) +- [SafeRpcUrl](type-aliases/SafeRpcUrl.md) +- [SignerType](type-aliases/SignerType.md) +- [ClaimIncentivesResponse](type-aliases/ClaimIncentivesResponse.md) +- [HttpRequestFunc](type-aliases/HttpRequestFunc.md) +- [OVMArgs](type-aliases/OVMArgs.md) +- [OVMRequestWithdrawalPayload](type-aliases/OVMRequestWithdrawalPayload.md) +- [EOAWithdrawalPayload](type-aliases/EOAWithdrawalPayload.md) +- [OVMDepositPayload](type-aliases/OVMDepositPayload.md) +- [EOADepositPayload](type-aliases/EOADepositPayload.md) + +## Variables + +- [CAPELLA\_FORK\_MAPPING](variables/CAPELLA_FORK_MAPPING.md) + +## Functions + +- [validateClusterLock](functions/validateClusterLock.md) +- [clusterConfigOrDefinitionHash](functions/clusterConfigOrDefinitionHash.md) +- [clusterLockHash](functions/clusterLockHash.md) +- [verifyDepositData](functions/verifyDepositData.md) diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.8/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..106c7de46a --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,36 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +# ClusterDefinition + +Defined in: [types.ts:121](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L121) + +Cluster definition data needed for dkg + +## Extends + +- [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Overrides | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | - | `ClusterPayload.name` | [types.ts:97](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L97) | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)[] | The cluster nodes operators addresses. | - | `ClusterPayload.operators` | [types.ts:100](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L100) | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)[] | The cluster validators information. | - | `ClusterPayload.validators` | [types.ts:103](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L103) | +| `deposit_amounts?` | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | - | `ClusterPayload.deposit_amounts` | [types.ts:106](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L106) | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | - | [types.ts:123](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L123) | +| `version` | `string` | The cluster configuration version. | - | - | [types.ts:126](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L126) | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | - | [types.ts:129](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L129) | +| `fork_version` | `string` | The cluster fork version. | - | - | [types.ts:132](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L132) | +| `uuid` | `string` | The cluster uuid. | - | - | [types.ts:135](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L135) | +| `timestamp` | `string` | The cluster creation timestamp. | - | - | [types.ts:138](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L138) | +| `config_hash` | `string` | The cluster configuration hash. | - | - | [types.ts:141](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L141) | +| `threshold` | `number` | The distributed validator threshold. | - | - | [types.ts:144](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L144) | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | - | [types.ts:147](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L147) | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | - | [types.ts:150](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L150) | +| `consensus_protocol?` | `string` | The consensus protocol e.g qbft. | `ClusterPayload.consensus_protocol` | - | [types.ts:153](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L153) | +| `target_gas_limit?` | `number` | The target gas limit where default is 36M. | `ClusterPayload.target_gas_limit` | - | [types.ts:156](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L156) | +| `compounding?` | `boolean` | A withdrawal mechanism with 0x02 withdrawal credentials. | `ClusterPayload.compounding` | - | [types.ts:159](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L159) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExistingExitValidationBlobData.md b/versioned_docs/version-v1.8/sdk/interfaces/ExistingExitValidationBlobData.md new file mode 100644 index 0000000000..f571985d1a --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExistingExitValidationBlobData.md @@ -0,0 +1,20 @@ +--- +sidebar_label: "ExistingExitValidationBlobData" +slug: /sdk/interfaces/existingexitvalidationblobdata +unlisted: true +--- + +# ExistingExitValidationBlobData + +Defined in: [types.ts:501](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L501) + +Represents the data structure for an already existing exit blob for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `public_key` | `string` | The BLS public key of the validator in hex format | [types.ts:505](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L505) | +| `epoch` | `string` | The epoch number when the exit is scheduled to occur | [types.ts:509](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L509) | +| `validator_index` | `string` | The unique index of the validator in the beacon chain | [types.ts:513](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L513) | +| `shares_exit_data` | `Record`\<`string`, \{ `partial_exit_signature`: `string`; \}\>[] | Array of distributed validator shares exit data, where each share contains the partial exit signature from each operator in the cluster | [types.ts:518](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L518) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitClusterConfig.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitClusterConfig.md new file mode 100644 index 0000000000..3a86d36eca --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitClusterConfig.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitClusterConfig" +slug: /sdk/interfaces/exitclusterconfig +unlisted: true +--- + +# ExitClusterConfig + +Defined in: [types.ts:443](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L443) + +Combined cluster information needed for exit validation in the SDK. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `definition` | [`ExitClusterDefinition`](ExitClusterDefinition.md) | The cluster definition with operators, fork version and threshold. | [types.ts:445](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L445) | +| `distributed_validators` | [`ExitDistributedValidator`](ExitDistributedValidator.md)[] | The cluster distributed validators. | [types.ts:448](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L448) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitClusterDefinition.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitClusterDefinition.md new file mode 100644 index 0000000000..79859a1a8c --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitClusterDefinition.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ExitClusterDefinition" +slug: /sdk/interfaces/exitclusterdefinition +unlisted: true +--- + +# ExitClusterDefinition + +Defined in: [types.ts:418](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L418) + +Represents the core definition of a cluster relevant for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `operators` | [`ExitOperator`](ExitOperator.md)[] | The cluster nodes operators with their ENRs. | [types.ts:420](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L420) | +| `fork_version` | `string` | The cluster fork version. | [types.ts:423](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L423) | +| `threshold` | `number` | The distributed validator threshold. | [types.ts:426](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L426) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitDistributedValidator.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitDistributedValidator.md new file mode 100644 index 0000000000..f5b618ab29 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitDistributedValidator.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitDistributedValidator" +slug: /sdk/interfaces/exitdistributedvalidator +unlisted: true +--- + +# ExitDistributedValidator + +Defined in: [types.ts:432](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L432) + +Represents a distributed validator's information relevant for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | [types.ts:434](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L434) | +| `public_shares` | `string`[] | The public key shares of the distributed validator. | [types.ts:437](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L437) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitOperator.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitOperator.md new file mode 100644 index 0000000000..33308efb1b --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitOperator.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "ExitOperator" +slug: /sdk/interfaces/exitoperator +unlisted: true +--- + +# ExitOperator + +Defined in: [types.ts:410](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L410) + +Represents the structure of an Ethereum operator for exit validation, primarily their ENR. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `enr` | `string` | The operator's Ethereum Node Record (ENR). | [types.ts:412](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L412) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationBlob.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationBlob.md new file mode 100644 index 0000000000..13029de46b --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationBlob.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitValidationBlob" +slug: /sdk/interfaces/exitvalidationblob +unlisted: true +--- + +# ExitValidationBlob + +Defined in: [types.ts:476](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L476) + +Represents a single partial exit blob for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `public_key` | `string` | The public key of the validator to exit. | [types.ts:478](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L478) | +| `signed_exit_message` | [`SignedExitValidationMessage`](SignedExitValidationMessage.md) | The signed exit message for the validator. | [types.ts:481](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L481) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationMessage.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationMessage.md new file mode 100644 index 0000000000..df7402241f --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationMessage.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitValidationMessage" +slug: /sdk/interfaces/exitvalidationmessage +unlisted: true +--- + +# ExitValidationMessage + +Defined in: [types.ts:454](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L454) + +Represents the message part of a signed exit for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `epoch` | `string` | The epoch at which the validator wishes to exit. | [types.ts:456](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L456) | +| `validator_index` | `string` | The index of the validator in the beacon chain. | [types.ts:459](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L459) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationPayload.md b/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationPayload.md new file mode 100644 index 0000000000..91ee5bc77d --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/ExitValidationPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ExitValidationPayload" +slug: /sdk/interfaces/exitvalidationpayload +unlisted: true +--- + +# ExitValidationPayload + +Defined in: [types.ts:487](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L487) + +Represents the overall exit payload structure for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `partial_exits` | [`ExitValidationBlob`](ExitValidationBlob.md)[] | Array of partial exits for validators. | [types.ts:489](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L489) | +| `share_idx` | `number` | Operator's share index (1-based). | [types.ts:492](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L492) | +| `signature` | `string` | Signature of the ExitValidationPayload by the operator. | [types.ts:495](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L495) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/README.md b/versioned_docs/version-v1.8/sdk/interfaces/README.md new file mode 100644 index 0000000000..c39173096c --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# Interfaces + diff --git a/versioned_docs/version-v1.8/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.8/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..df9acb8690 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,26 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +# RewardsSplitPayload + +Defined in: [types.ts:193](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L193) + +OWR and Split Proxy Params + +## Extends + +- [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| ------ | ------ | ------ | ------ | ------ | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | [types.ts:178](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L178) | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | [types.ts:181](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L181) | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | [types.ts:184](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L184) | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | [types.ts:187](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L187) | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | [types.ts:195](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L195) | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | [types.ts:198](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L198) | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | [types.ts:201](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L201) | diff --git a/versioned_docs/version-v1.8/sdk/interfaces/SignedExitValidationMessage.md b/versioned_docs/version-v1.8/sdk/interfaces/SignedExitValidationMessage.md new file mode 100644 index 0000000000..8896c283a1 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/interfaces/SignedExitValidationMessage.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "SignedExitValidationMessage" +slug: /sdk/interfaces/signedexitvalidationmessage +unlisted: true +--- + +# SignedExitValidationMessage + +Defined in: [types.ts:465](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L465) + +Represents a signed exit message for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`ExitValidationMessage`](ExitValidationMessage.md) | The exit message containing epoch and validator index. | [types.ts:467](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L467) | +| `signature` | `string` | BLS signature of the exit message. | [types.ts:470](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L470) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.8/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..c1e08cd8ce --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +# BuilderRegistration + +> **BuilderRegistration** = `object` + +Defined in: [types.ts:290](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L290) + +Pre-generated Signed Validator Builder Registration + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | [types.ts:292](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L292) | +| `signature` | `string` | BLS signature of the builder registration message. | [types.ts:295](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L295) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.8/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..4053b6e0b4 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +# BuilderRegistrationMessage + +> **BuilderRegistrationMessage** = `object` + +Defined in: [types.ts:273](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L273) + +Unsigned DV Builder Registration Message + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient` | `string` | The DV fee recipient. | [types.ts:275](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L275) | +| `gas_limit` | `number` | Default is 30000000. | [types.ts:278](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L278) | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | [types.ts:281](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L281) | +| `pubkey` | `string` | The public key of the DV. | [types.ts:284](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L284) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClaimIncentivesResponse.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClaimIncentivesResponse.md new file mode 100644 index 0000000000..4167ef05d5 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClaimIncentivesResponse.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "ClaimIncentivesResponse" +slug: /sdk/type-aliases/claimincentivesresponse +unlisted: true +--- + +# ClaimIncentivesResponse + +> **ClaimIncentivesResponse** = `object` + +Defined in: [types.ts:405](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L405) + +claimIncentives Response diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClaimableIncentives.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClaimableIncentives.md new file mode 100644 index 0000000000..0152874a04 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClaimableIncentives.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClaimableIncentives" +slug: /sdk/type-aliases/claimableincentives +unlisted: true +--- + +# ClaimableIncentives + +> **ClaimableIncentives** = `object` + +Defined in: [types.ts:361](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L361) + +Claimable Obol Incentives + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `operator_address` | `string` | Operator Address. | [types.ts:363](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L363) | +| `amount` | `string` | The amount the recipient is entitled to. | [types.ts:366](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L366) | +| `index` | `number` | The recipient's index in the Merkle tree. | [types.ts:369](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L369) | +| `merkle_proof` | `string`[] | The Merkle proof (an array of hashes) generated for the recipient. | [types.ts:372](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L372) | +| `contract_address` | `string` | The MerkleDistributor contract address. | [types.ts:375](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L375) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..db6c5d1857 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +# ClusterCreator + +> **ClusterCreator** = `object` + +Defined in: [types.ts:74](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L74) + +Cluster creator data + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The creator address. | [types.ts:76](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L76) | +| `config_signature?` | `string` | The cluster configuration signature. | [types.ts:78](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L78) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..4f5b9f50a7 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +# ClusterLock + +> **ClusterLock** = `object` + +Defined in: [types.ts:341](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L341) + +Cluster Details after DKG is complete + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | [types.ts:343](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L343) | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)[] | The cluster distributed validators. | [types.ts:346](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L346) | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | [types.ts:349](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L349) | +| `lock_hash` | `string` | The hash of the cluster lock. | [types.ts:352](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L352) | +| `node_signatures?` | `string`[] | Node Signature for the lock hash by the node secp256k1 key. | [types.ts:355](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L355) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..ce07cd83e0 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +# ClusterOperator + +> **ClusterOperator** = `object` + +Defined in: [types.ts:45](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L45) + +Node operator data + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | The operator address. | [types.ts:47](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L47) | +| `enr?` | `string` | The operator ethereum node record. | [types.ts:50](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L50) | +| `fork_version?` | `string` | The cluster fork_version. | [types.ts:53](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L53) | +| `version?` | `string` | The cluster version. | [types.ts:56](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L56) | +| `enr_signature?` | `string` | The operator enr signature. | [types.ts:59](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L59) | +| `config_signature?` | `string` | The operator configuration signature. | [types.ts:62](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L62) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..464c6b07d0 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,28 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +# ClusterPayload + +> **ClusterPayload** = `object` + +Defined in: [types.ts:95](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L95) + +Cluster configuration + +## Extended by + +- [`ClusterDefinition`](../interfaces/ClusterDefinition.md) + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `name` | `string` | The cluster name. | [types.ts:97](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L97) | +| `operators` | [`ClusterOperator`](ClusterOperator.md)[] | The cluster nodes operators addresses. | [types.ts:100](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L100) | +| `validators` | [`ClusterValidator`](ClusterValidator.md)[] | The cluster validators information. | [types.ts:103](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L103) | +| `deposit_amounts?` | `string`[] \| `null` | The cluster partial deposits in gwei or 32000000000. | [types.ts:106](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L106) | +| `compounding?` | `boolean` | A withdrawal mechanism with 0x02 withdrawal credentials. | [types.ts:109](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L109) | +| `target_gas_limit?` | `number` | The target gas limit where default is 36M. | [types.ts:112](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L112) | +| `consensus_protocol?` | `string` | The consensus protocol e.g qbft. | [types.ts:115](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L115) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..83cc6e5d73 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +# ClusterValidator + +> **ClusterValidator** = `object` + +Defined in: [types.ts:84](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L84) + +Validator withdrawal configuration + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | [types.ts:86](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L86) | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | [types.ts:89](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L89) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.8/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..8dee150d5f --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +# DepositData + +> **DepositData** = `object` + +Defined in: [types.ts:301](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L301) + +Required deposit data for validator activation + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | The public key of the distributed validator. | [types.ts:303](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L303) | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | [types.ts:306](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L306) | +| `amount` | `string` | 32 ethers. | [types.ts:309](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L309) | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | [types.ts:312](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L312) | +| `signature` | `string` | BLS signature of the deposit message. | [types.ts:315](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L315) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.8/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..7692352bf5 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +# DistributedValidator + +> **DistributedValidator** = `object` + +Defined in: [types.ts:321](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L321) + +Required deposit data for validator activation + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | [types.ts:323](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L323) | +| `public_shares` | `string`[] | The public key of the node distributed validator share. | [types.ts:326](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L326) | +| `deposit_data?` | `Partial`\<[`DepositData`](DepositData.md)\> | The deposit data for activating the DV. | [types.ts:329](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L329) | +| `partial_deposit_data?` | `Partial`\<[`DepositData`](DepositData.md)\>[] | The deposit data with partial amounts or full amount for activating the DV. | [types.ts:332](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L332) | +| `builder_registration?` | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | [types.ts:335](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L335) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/EOADepositPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/EOADepositPayload.md new file mode 100644 index 0000000000..35d1490605 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/EOADepositPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "EOADepositPayload" +slug: /sdk/type-aliases/eoadepositpayload +unlisted: true +--- + +# EOADepositPayload + +> **EOADepositPayload** = `object` + +Defined in: [types.ts:673](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L673) + +Payload for depositing to batch deposit contract + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `deposits` | `object`[] | Array of deposit objects | [types.ts:675](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L675) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/EOAWithdrawalPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/EOAWithdrawalPayload.md new file mode 100644 index 0000000000..b32dcf54bb --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/EOAWithdrawalPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "EOAWithdrawalPayload" +slug: /sdk/type-aliases/eoawithdrawalpayload +unlisted: true +--- + +# EOAWithdrawalPayload + +> **EOAWithdrawalPayload** = `object` + +Defined in: [types.ts:637](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L637) + +Payload for requesting withdrawal from EOA contract + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | Validator public key in hex format | [types.ts:639](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L639) | +| `allocation` | `number` | Withdrawal amount in ETH | [types.ts:642](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L642) | +| `requiredFee` | `string` | Required fee in wei | [types.ts:645](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L645) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.8/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..db402d930a --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +# ETH\_ADDRESS + +> **ETH\_ADDRESS** = `string` + +Defined in: [types.ts:381](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L381) + +String expected to be Ethereum Address diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/HttpRequestFunc.md b/versioned_docs/version-v1.8/sdk/type-aliases/HttpRequestFunc.md new file mode 100644 index 0000000000..a8cbe0f159 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/HttpRequestFunc.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "HttpRequestFunc()" +slug: /sdk/type-aliases/httprequestfunc +unlisted: true +--- + +# HttpRequestFunc() + +> **HttpRequestFunc** = (`url`, `config?`) => `Promise`\<`any`\> + +Defined in: [types.ts:558](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L558) + +Generic HTTP request function type. +Args: + url: string - The URL to request. + config?: Record\ - Optional request configuration (e.g., method, headers, body for POST). +Returns: + Promise\ - The response data. + +## Parameters + +| Parameter | Type | +| ------ | ------ | +| `url` | `string` | +| `config?` | `Record`\<`string`, `any`\> | + +## Returns + +`Promise`\<`any`\> diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMArgs.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMArgs.md new file mode 100644 index 0000000000..4cfb912acc --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMArgs.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "OVMArgs" +slug: /sdk/type-aliases/ovmargs +unlisted: true +--- + +# OVMArgs + +> **OVMArgs** = `object` + +Defined in: [types.ts:566](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L566) + +OVM Arguments for contract creation + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `OVMOwnerAddress` | `string` | Owner address for the OVM contract. | [types.ts:568](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L568) | +| `principalRecipient` | `string` | Principal recipient address. | [types.ts:571](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L571) | +| `rewardRecipient` | `string` | Rewards recipient of the cluster. | [types.ts:574](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L574) | +| `principalThreshold` | `number` | Principal threshold in ETH for OVM contract. | [types.ts:577](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L577) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMBaseSplitPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMBaseSplitPayload.md new file mode 100644 index 0000000000..92e630877b --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMBaseSplitPayload.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "OVMBaseSplitPayload" +slug: /sdk/type-aliases/ovmbasesplitpayload +unlisted: true +--- + +# OVMBaseSplitPayload + +> **OVMBaseSplitPayload** = `object` + +Defined in: [types.ts:207](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L207) + +OVM and SplitV2 Base Params + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `rewardSplitRecipients` | [`SplitV2Recipient`](SplitV2Recipient.md)[] | The split recipients addresses and splits. | [types.ts:209](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L209) | +| `OVMOwnerAddress` | `string` | Owner address for the OVM contract. | [types.ts:212](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L212) | +| `splitOwnerAddress?` | `string` | Owner address for the splitter contracts. | [types.ts:215](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L215) | +| `principalThreshold?` | `number` | Principal threshold in ETH for OVM contract. | [types.ts:218](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L218) | +| `distributorFeePercent?` | `number` | Distributor fee percentage (0-10). | [types.ts:221](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L221) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMDepositPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMDepositPayload.md new file mode 100644 index 0000000000..e8bed51054 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMDepositPayload.md @@ -0,0 +1,20 @@ +--- +sidebar_label: "OVMDepositPayload" +slug: /sdk/type-aliases/ovmdepositpayload +unlisted: true +--- + +# OVMDepositPayload + +> **OVMDepositPayload** = `object` + +Defined in: [types.ts:651](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L651) + +Payload for depositing to OVM contract with multicall3 + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `ovmAddress` | `string` | OVM contract address | [types.ts:653](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L653) | +| `deposits` | `object`[] | Array of deposit objects | [types.ts:656](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L656) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMRequestWithdrawalPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMRequestWithdrawalPayload.md new file mode 100644 index 0000000000..fac62c4c85 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMRequestWithdrawalPayload.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "OVMRequestWithdrawalPayload" +slug: /sdk/type-aliases/ovmrequestwithdrawalpayload +unlisted: true +--- + +# OVMRequestWithdrawalPayload + +> **OVMRequestWithdrawalPayload** = `object` + +Defined in: [types.ts:620](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L620) + +Payload for requesting withdrawal from OVM contract + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `withdrawalFees` | `string` | request withdrawal fees in wei | [types.ts:622](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L622) | +| `ovmAddress` | `string` | OVM contract address | [types.ts:625](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L625) | +| `pubKeys` | `string`[] | Array of validator public keys in bytes format | [types.ts:628](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L628) | +| `amounts` | `string`[] | Array of withdrawal amounts in gwei (uint64) as strings | [types.ts:631](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L631) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMRewardsSplitPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMRewardsSplitPayload.md new file mode 100644 index 0000000000..3209f9ab1f --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMRewardsSplitPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "OVMRewardsSplitPayload" +slug: /sdk/type-aliases/ovmrewardssplitpayload +unlisted: true +--- + +# OVMRewardsSplitPayload + +> **OVMRewardsSplitPayload** = [`OVMBaseSplitPayload`](OVMBaseSplitPayload.md) & `object` + +Defined in: [types.ts:227](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L227) + +OVM and SplitV2 Params for rewards-only split + +## Type Declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `principalRecipient` | `string` | Principal recipient address (single address for rewards-only split). | [types.ts:229](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L229) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMSplitPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMSplitPayload.md new file mode 100644 index 0000000000..75fa7ed20f --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMSplitPayload.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "OVMSplitPayload" +slug: /sdk/type-aliases/ovmsplitpayload +unlisted: true +--- + +# OVMSplitPayload + +> **OVMSplitPayload** = [`OVMRewardsSplitPayload`](OVMRewardsSplitPayload.md) \| [`OVMTotalSplitPayload`](OVMTotalSplitPayload.md) + +Defined in: [types.ts:243](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L243) + +Union type for both OVM split scenarios diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OVMTotalSplitPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OVMTotalSplitPayload.md new file mode 100644 index 0000000000..88297e78fd --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OVMTotalSplitPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "OVMTotalSplitPayload" +slug: /sdk/type-aliases/ovmtotalsplitpayload +unlisted: true +--- + +# OVMTotalSplitPayload + +> **OVMTotalSplitPayload** = [`OVMBaseSplitPayload`](OVMBaseSplitPayload.md) & `object` + +Defined in: [types.ts:235](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L235) + +OVM and SplitV2 Params for total split scenario + +## Type Declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `principalSplitRecipients` | [`SplitV2Recipient`](SplitV2Recipient.md)[] | Principal recipients addresses and splits (array for total split scenario). | [types.ts:237](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L237) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OWRTranches.md b/versioned_docs/version-v1.8/sdk/type-aliases/OWRTranches.md new file mode 100644 index 0000000000..28d76a6e1e --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OWRTranches.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "OWRTranches" +slug: /sdk/type-aliases/owrtranches +unlisted: true +--- + +# OWRTranches + +> **OWRTranches** = `object` + +Defined in: [types.ts:259](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L259) + +OWR Tranches + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `principalRecipient` | [`ETH_ADDRESS`](ETH_ADDRESS.md) | Address that will reclaim validator principal after exit. | [types.ts:261](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L261) | +| `rewardRecipient` | [`ETH_ADDRESS`](ETH_ADDRESS.md) | Address that will reclaim validator rewards during operation. | [types.ts:264](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L264) | +| `amountOfPrincipalStake` | `number` | Amount of principal staked. | [types.ts:267](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L267) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..0f576a1bc9 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +# OperatorPayload + +> **OperatorPayload** = `Partial`\<[`ClusterOperator`](ClusterOperator.md)\> & `Required`\<`Pick`\<[`ClusterOperator`](ClusterOperator.md), `"enr"` \| `"version"`\>\> + +Defined in: [types.ts:68](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L68) + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/ProviderType.md b/versioned_docs/version-v1.8/sdk/type-aliases/ProviderType.md new file mode 100644 index 0000000000..a1d061727c --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/ProviderType.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "ProviderType" +slug: /sdk/type-aliases/providertype +unlisted: true +--- + +# ProviderType + +> **ProviderType** = `Provider` \| `JsonRpcProvider` \| `JsonRpcApiProvider` \| `ethers.BrowserProvider` + +Defined in: [types.ts:386](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L386) + +Provider Types diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/README.md b/versioned_docs/version-v1.8/sdk/type-aliases/README.md new file mode 100644 index 0000000000..bf0d8a2b37 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# Type-Aliases + diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/SafeRpcUrl.md b/versioned_docs/version-v1.8/sdk/type-aliases/SafeRpcUrl.md new file mode 100644 index 0000000000..25f2a4b2a8 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/SafeRpcUrl.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "SafeRpcUrl" +slug: /sdk/type-aliases/saferpcurl +unlisted: true +--- + +# SafeRpcUrl + +> **SafeRpcUrl** = `string` + +Defined in: [types.ts:395](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L395) + +Safe Wallet Provider Types diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/SignerType.md b/versioned_docs/version-v1.8/sdk/type-aliases/SignerType.md new file mode 100644 index 0000000000..6ab97e44f0 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/SignerType.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "SignerType" +slug: /sdk/type-aliases/signertype +unlisted: true +--- + +# SignerType + +> **SignerType** = `JsonRpcSigner` \| `Wallet` + +Defined in: [types.ts:400](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L400) + +Signer Types diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.8/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..c359f70e6b --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +# SplitRecipient + +> **SplitRecipient** = `object` + +Defined in: [types.ts:165](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L165) + +Split Recipient Keys + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `account` | `string` | The split recipient address. | [types.ts:167](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L167) | +| `percentAllocation` | `number` | The recipient split. | [types.ts:170](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L170) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/SplitV2Recipient.md b/versioned_docs/version-v1.8/sdk/type-aliases/SplitV2Recipient.md new file mode 100644 index 0000000000..44997b67dd --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/SplitV2Recipient.md @@ -0,0 +1,20 @@ +--- +sidebar_label: "SplitV2Recipient" +slug: /sdk/type-aliases/splitv2recipient +unlisted: true +--- + +# SplitV2Recipient + +> **SplitV2Recipient** = `object` + +Defined in: [types.ts:248](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L248) + +SplitV2 Recipient structure + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | Recipient address. | [types.ts:250](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L250) | +| `percentAllocation` | `number` | Percentage allocation (0-100 with up to 4 decimals). | [types.ts:253](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L253) | diff --git a/versioned_docs/version-v1.8/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.8/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..ed473d1093 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,25 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +# TotalSplitPayload + +> **TotalSplitPayload** = `object` + +Defined in: [types.ts:176](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L176) + +Split Proxy Params + +## Extended by + +- [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)[] | The split recipients addresses and splits. | [types.ts:178](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L178) | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | [types.ts:181](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L181) | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | [types.ts:184](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L184) | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | [types.ts:187](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L187) | diff --git a/versioned_docs/version-v1.8/sdk/variables/CAPELLA_FORK_MAPPING.md b/versioned_docs/version-v1.8/sdk/variables/CAPELLA_FORK_MAPPING.md new file mode 100644 index 0000000000..cbf011fe35 --- /dev/null +++ b/versioned_docs/version-v1.8/sdk/variables/CAPELLA_FORK_MAPPING.md @@ -0,0 +1,14 @@ +--- +sidebar_label: "CAPELLA_FORK_MAPPING" +slug: /sdk/variables/capella_fork_mapping +unlisted: true +--- + +# CAPELLA\_FORK\_MAPPING + +> `const` **CAPELLA\_FORK\_MAPPING**: `Record`\<`string`, `string`\> + +Defined in: [constants.ts:292](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/constants.ts#L292) + +Maps base fork versions to their corresponding Capella fork versions. +Example: Mainnet Capella fork version. diff --git a/versioned_docs/version-v1.8/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.8/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..5368c6e179 --- /dev/null +++ b/versioned_docs/version-v1.8/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# walkthroughs + diff --git a/versioned_docs/version-v1.8/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.8/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.8/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_docs/version-v1.9/README.md b/versioned_docs/version-v1.9/README.md new file mode 100644 index 0000000000..d56aef220c --- /dev/null +++ b/versioned_docs/version-v1.9/README.md @@ -0,0 +1,28 @@ +--- +title: "Introduction" +description: "Documentation, integration guides, and protocol specifications" +sidebar_label: "Introduction" +slug: /learn/readme +--- + +# Introduction + +### Welcome to Obol! + +Obol builds Distributed Validator Technology (DVT), which empowers node operators, staking protocols, and institutions run Ethereum validators that are more secure, fault-tolerant, and performant. DVT benefits both operators and capital allocators while strengthening the network itself by reducing centralization risk and protecting against supermajority failures. Obol DVs are the staking endgame. + +Whether you’re here to learn about DVT, integrate it into your staking stack, or want to stake your ETH on DVs, these docs will help you get started. + +*** + +### Quick start + + + + diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/README.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/README.md new file mode 100644 index 0000000000..991baa0e5d --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Advanced Guides" +slug: /advanced-and-troubleshooting/advanced +--- + +# Advanced Guides + diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/adv-docker-configs.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/adv-docker-configs.md new file mode 100644 index 0000000000..91890c82c5 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/adv-docker-configs.md @@ -0,0 +1,37 @@ +--- +description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration." +sidebar_label: "Advanced Docker Configs" +slug: /advanced-and-troubleshooting/advanced/adv-docker-configs +--- + +# 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 version-controlled 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 `tempo`. 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 +``` diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md new file mode 100644 index 0000000000..d4f8808d8c --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md @@ -0,0 +1,80 @@ +--- +description: "Prepare an alternative deposit for an unused validator" +sidebar_label: "Alter Withdrawal Addresses" +slug: /advanced-and-troubleshooting/advanced/alter-withdrawal-addresses +--- + +# Alter Withdrawal Addresses + +:::warning +Please take care when changing a withdrawal address for an inactivated validator. Activating a validator that exits to a withdrawal address you don't control likely means your funds are lost. + +Also be careful as to the trustworthiness of the original withdrawal address. They [could attempt to front-run](https://medium.com/immunefi/rocketpool-lido-frontrunning-bug-fix-postmortem-e701f26d7971) the alternative deposit, and end up receiving the new depositor's funds to their withdrawal address. +::: + +On occasion it can be useful to be able to change the withdrawal address specified for an already created but unused distributed validator. For example if they are unneeded extra capacity, or if the withdrawal address to be used was not known at cluster creation time and a trusted placeholder address was used instead. The `charon deposit` commands allow you to sign alternative deposit messages for **inactive validators** with the help of the Obol [API](../../api/what-is-this-api.md). + +:::info +If you want to change the withdrawal address of a running validator, consider a validator [consolidation](operator-rotation.md) instead. +::: + +## Sign an alternative deposit message + +A threshold of operators must decide which public keys they are changing the withdrawal address for, and what the new withdrawal address will be. Then each run the `charon deposit sign` command with their partial private keys and the appropriate (identical) flags. + +**Single public key** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" +``` + +:::info +`validator-public-keys` are the distributed validator public keys for which the alternative deposit data should be signed (find them in your cluster\_lock.json file in the `distributed_validator_public_keys` mapping or on the DV Launchpad). `withdrawal-addresses` are the new withdrawal address(es) for which the new deposit data should be signed. There should either be the same amount as `validator-public-keys` specified, or a single address that will be used for all public keys specified. + +Optionally, users can also specify multiple different `deposit-amounts` (defaults to only `32`) to be prepared. +::: + +**Multiple public keys, multiple withdrawal addresses** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045,0x1db3439a222c519ab44bb1144fc28167b4fa6ee6" +``` + +**Multiple public keys, single withdrawal address** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" +``` + +## Fetch full deposit data + +After a threshold of operators have submitted partial alternative deposits, a full aggregated deposit message can be fetched from Obol API. + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit fetch \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ +``` + +:::info +`validator-public-keys` are the validator public keys for which the new deposit data should be fetched. +::: + +After a successful fetch the new deposit data files are saved in `.charon/deposit-data-.json`. + +If there are not enough partial signatures, an error message will be returned. + +```sh +17:18:40.771 ERRO cmd Application failed to start: fetch full deposit data from Obol API: not enough partial signatures to meet threshold {"submitted_public_keys": "[0x8677e2014a173f72b3d4528893cb01881549631c2a39d90d7c19c230299a57440e73c82c7daf1d72713b1e26e42bae99]", "submitted_public_keys_length": 1, "required_threshold": 3} +``` + +This deposit message file can be used with a deposit interface, to activate the validator on the Ethereum deposit contract. + +:::danger +Please take care not to mistakenly activate the old `deposit-data.json` file when the cluster was originally created, containing the withdrawal address you hope to replace. If you activate a validator with a withdrawal address you don't control, your funds are likely lost. +::: diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/assign-ovm-roles.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/assign-ovm-roles.md new file mode 100644 index 0000000000..318e69cf62 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/assign-ovm-roles.md @@ -0,0 +1,93 @@ +--- +description: "Learn how to assign permissions within the Obol Vault Manager (OVM) smart contract using the efficient bitwise role system." +sidebar_label: "Assign OVM Roles" +slug: /advanced-and-troubleshooting/advanced/assign-ovm-roles +--- + +# Assign OVM Roles + +This guide explains how to assign permissions within the Obol Vault Manager (OVM) smart contract using its bitwise role system and outlines key security recommendations. + +*** + +## 1. Understanding the Bitwise Role System + +The OVM contract manages permissions by assigning each role a unique power-of-two value (a single binary bit). To grant multiple roles, you simply add (or bitwise OR) their values together to produce a single, final integer that the smart contract reads. + +### Contract Role Definitions + +| Role Name | Decimal Value | Hex Value | Primary Purpose | +| -------------------------- | ------------- | --------- | --------------------------------------------- | +| **`WITHDRAWAL_ROLE`** | 1 | `0x01` | Initiate validator withdrawals/claims. | +| **`CONSOLIDATION_ROLE`** | 2 | `0x02` | Initiate validator consolidation (migration). | +| **`SET_BENEFICIARY_ROLE`** | 4 | `0x04` | Set/change the principal/withdrawal address. | +| **`RECOVER_FUNDS_ROLE`** | 8 | `0x08` | Emergency recovery of stuck assets. | +| **`SET_REWARD_ROLE`** | 16 | `0x10` | Set/change the reward fee recipient address. | +| **`DEPOSIT_ROLE`** | 32 | `0x20` | Submit validator deposit data. | + +## 2. Guide to Assigning and Managing Roles + +The easiest way to generate the required hex code is by using the dedicated calculator tool. + +### Step 1: Find the hex code (Using the Calculator) + +Use the following interactive tool to instantly find the code for your required role combination: + +* [**OVM Roles Calculator**](https://dazzling-genie-4aaac7.netlify.app/) + +1. **Select Roles:** Go to the calculator and click the **Checkboxes** for all the roles you need to grant. +2. **Retrieve Code:** The calculator will automatically calculate and display the final **Total hex code** (e.g., `0x11`) and **Total Decimal Code** (e.g., 17). Use the **Total hex code** in the next stage. + +### Step 2: Assign the Roles On-Chain + +Roles are assigned using the **`grantRoles`** function on the OVM smart contract. + +1. **Go to Etherscan:** Navigate to the Block Explorer page for your deployed OVM smart contract. +2. **Access Write Contract:** Click the **"Contract"** tab, and then the **"Write Contract"** sub-tab. +3. **Connect Wallet:** Click **"Connect to Web3"** and connect the wallet that currently holds **ownership** of the OVM contract. +4. **Execute `grantRoles`:** + * Find the function **`grantRoles`**. + * **`user (address)`:** Enter the wallet address you want to grant permissions to (this is the target operator's address). + * **`roles (uint256)`:** Input the **Decimal Value** (e.g., `17`) or **Hex Value** (e.g., `0x11`) copied from the calculator. + * Click **"Write"** and approve the transaction. + +![](/img/gitbook/AssignOVMRoles1.png) + +## 3. Review the Roles + +1. Assigned roles will show up in the Launchpad to the designated address. + +![](/img/gitbook/AssignOVMRoles2.png) + +2. Sometimes the Launchpad may take a short time to reflect role updates due to RPC issues.. Try refreshing if this occurs. You can also use Etherscan directly to confirm roles. + +![](/img/gitbook/AssignOVMRoles3.png) + +## 4. Security and Recommendations 🔒 + +The security of the cluster relies entirely on the assignment and control of these roles. Follow these best practices: + +### A. Principle of Least Privilege + +* **Avoid `0x3F` (All Roles):** Never grant the full combination code (`0x3F` or 63) to any address that doesn't absolutely require it (like the primary owner/governance multi-sig). +* **Role Separation:** Grant only the specific roles an operator needs for their job. For example: + * A technical operator managing deposits/withdrawals needs `WITHDRAWAL_ROLE` (1), `CONSOLIDATION_ROLE` (2), and `DEPOSIT_ROLE` (32). + * A separate, highly-trusted governance multi-sig should hold **high-privilege roles** like `SET_BENEFICIARY_ROLE` (4), `SET_REWARD_ROLE` (16), and `RECOVER_FUNDS_ROLE` (8). + +### B. Ownership & Trust + +* **Secure the Owner:** The address that can call `grantRoles` and `revokeRoles` is the most powerful. This address **must be a hardware wallet or, ideally, a Gnosis SAFE multi-sig wallet.** +* **Cluster Creation Timing:** It is recommended to **grant final roles before sharing cluster invites** with external invitees. This ensures the security model is locked down before the cluster scales. +* **Renounce Ownership (Conditional):** If the cluster's roles are intended to be fixed forever (e.g., in a fully immutable system), you can **renounce ownership** after setting the final roles. However, if any role needs to be modifiable later (like changing the fee recipient), the owner must retain the ability to execute `grantRoles`. + +![](/img/gitbook/AssignOVMRoles4.png) + +## 5. Miscellaneous: How does Bitwise Logic Work? + +The final hex code is generated by the **Bitwise OR** operation. Since every role value is a unique power of two, the code for any combination is simply the sum of the desired decimal values. + +| Role Combination Requested | Decimal Addition | Bitwise OR (Binary) | Final hex code | +| ------------------------------------- | ---------------- | ------------------------------------------------------- | -------------- | +| **WITHDRAWAL** and **DEPOSIT** | 1+32=33 | `000001` \| `100000` = `100001` | **`0x21`** | +| **CONSOLIDATION** and **SET\_REWARD** | 2+16=18 | `000010` \| `010000` = `010010` | **`0x12`** | +| **All 4 Basic Roles** | 1+2+4+8=15 | `000001` \| `000010` \| `000100` \| `001000` = `001111` | **`0x0F`** | diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/beacon-node-authentication.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/beacon-node-authentication.md new file mode 100644 index 0000000000..ec63bbee2f --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/beacon-node-authentication.md @@ -0,0 +1,39 @@ +--- +description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control." +sidebar_label: "Beacon node authentication" +slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication +--- + +# Beacon node authentication + +## HTTP Basic Access Authentication + +If you want to use Charon with an [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic ` where `Authorization` will be the header key and `Basic ` will be the header value. The `` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`. + +:::warning +These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node. +::: + +## Usage example + +Suppose we have an HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command: + +``` +echo -n "john:doe" | base64 +``` + +Then you could pass the flag to your Charon instance like this: + +``` +charon run --beacon-node-headers="Authorization=Basic am9objpkb2U=" +``` + +Or you could specify it as an environment variable like this: + +``` +CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U=" +``` + +:::info +Note that 'Authorization' is followed with an `=` rather than the usual `:`. +::: diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/client-swap.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/client-swap.md new file mode 100644 index 0000000000..45d76fb75e --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/client-swap.md @@ -0,0 +1,177 @@ +--- +description: "Swap EL, CL, VC and MEV clients in the stack." +sidebar_label: "Swapping Clients" +slug: /advanced-and-troubleshooting/advanced/client-swap +--- + +# Swapping Clients + +If you are using CDVN, the default stack is: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | --------- | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | + +However, to achieve greater resilience through client diversity, it is preferred to run a variety of clients across your cluster, ideally ensuring no single EL/CL/VC runs on one third of the nodes or more. CDVN supports changing from the default clients. + +Currently supported client options are: + +| Execution layer | Consensus layer | Distributed validator | Validator client | MEV | +| --------------- | --------------- | --------------------- | ---------------- | ------------ | +| Nethermind | Lighthouse | Charon | Lodestar | MEV boost | +| Reth | Grandine | | Nimbus | Commit boost | +| | Lodestar | | Prysm | | +| | Teku | | Teku | | + +For support between different combinations, refer to Charon's compatibility matrix, found in the [prepare section of the docs](../../run-a-dv/prepare/how_where_dvs.md) or under [release notes](https://github.com/ObolNetwork/charon/releases/) for each release. + +:::info +As CDVN natively supports more clients, the number of possible combinations grows quickly. We test extensively, but cannot guarantee the performance of all possible client combos. If you run a mixed-client cluster, monitor performance and be ready to swap to another client if you observe issues. +::: + +:::info +There is currently an incompatibility between validator clients that may cause attestation aggregation duties to fail. Aggregation duties are not economically rewarded nor punished for their completion. + +To ensure aggregations succeed; have at least threshold of nodes in the cluster running one of Lodestar, Lighthouse, and Nimbus, or alternatively; have a threshold of nodes in the cluster running one of Teku and Prysm. This incompatibility will be remediated in upcoming client releases. +::: + +:::warning +**Lodestar's validator** client's default behaviour is to skip the next slot if it fails an attestation or aggregation. This can impact your cluster's performance, particularly if you have more than the fault tolerance threshold of your cluster running Lodestar's validator client, and many validators running in the cluster. + +If your cluster is not successfully aggregating, you should ideally swap to a set of compatible validator clients listed above, along with ensuring your clients have the appropriate [`--distributed` flag](../troubleshooting/client_configurations.md) set to enable distributed aggregation mode. Failing that, you can add the flag `--slotSkip false` to your `lodestar vc` process, (requires lodestar to be version `v1.37.0` and newer) or set `VC_LODESTAR_DISABLE_SLOT_SKIP=true` in your `.env` file if you're using (L)[CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node). This disables the slot skipping feature. +::: + +## Choosing clients in fresh cluster + +In order to choose which clients to use in a new cluster, simply leave uncommented (only) the desired `EL`, `CL`, `MEV` or `VC` variables in the `.env` file. There must be only one client per component. The cluster will use the respective client for each component. + +## Swapping clients in an already running cluster + +:::warning +For ([L](https://github.com/obolNetwork/lido-charon-distributed-validator-node))[CDVN](https://github.com/obolNetwork/charon-distributed-validator-node) users who created their `.env` file before the release of charon `v1.8.0`, there are breaking changes between then and the current multi-client `.env` file setup. The minimal addition to an older version of the `.env` file compatible with the current versions of the repos is to add `COMPOSE_PROFILES=el_nethermind,cl_lighthouse,dv_charon,vc_lodestar,mev_mevboost` to your existing `.env` file. Some environment variables were renamed in order to be client-agnostic. **If you had set these environment variables to custom values in your `.env`, you need to set the new variables to your custom values**. They serve the same purpose. +::: + +| Old | New | +| ------------------------------- | ------------------------------------ | +| NETHERMIND\_PORT\_P2P | EL\_PORT\_P2P | +| NETHERMIND\_IP\_HTTP | EL\_IP\_HTTP | +| NETHERMIND\_PORT\_HTTP | EL\_PORT\_HTTP | +| NETHERMIND\_IP\_ENGINE | EL\_IP\_ENGINE | +| NETHERMIND\_PORT\_ENGINE | EL\_PORT\_ENGINE | +| LIGHTHOUSE\_PORT\_P2P | CL\_PORT\_P2P | +| LODESTAR\_PORT\_METRICS | VC\_PORT\_METRICS | +| MEVBOOST\_TIMEOUT\_GETHEADER | MEV\_TIMEOUT\_GETHEADER | +| MEVBOOST\_TIMEOUT\_GETPAYLOAD | MEV\_TIMEOUT\_GETPAYLOAD | +| MEVBOOST\_TIMEOUT\_REGVAL | MEV\_TIMEOUT\_REGVAL | +| MEVBOOST\_RELAYS | MEV\_RELAYS | +| NETHERMIND\_PROMTAIL\_MONITORED | EL\_NETHERMIND\_PROMTAIL\_MONITORED | +| LIGHTHOUSE\_PROMTAIL\_MONITORED | CL\_LIGHTHOUSE\_PROMTAIL\_MONITORED | +| LODESTAR\_PROMTAIL\_MONITORED | VC\_LODESTAR\_PROMTAIL\_MONITORED | +| MEV\_BOOST\_PROMTAIL\_MONITORED | MEV\_MEV\_BOOST\_PROMTAIL\_MONITORED | + +1. Copy the new `.env.sample.` file to `.env`. +2. Comment or uncomment your preferred Execution, Consensus, Validator, and MEV clients and save the file. +3. Stop the existing cluster that uses the old environment file. + +```sh +docker compose --profile "" down +``` + +3. Start the node again to pick up the changes to the `.env` file. + +```sh +docker compose up -d +``` + +Your node should start up with the new clients. + +### Swap Consensus layer + +:::info +The code snippets under those steps are assuming you are swapping from Lighthouse CL to Grandine CL and you. +::: + +1. Stop the existing consensus layer client container. + +:::info +If you do not want to experience downtime while the new beacon node is syncing, you can set a fallback beacon node for Charon (`CHARON_FALLBACK_BEACON_NODE_ENDPOINTS` env variable) that will be used while the new BN is syncing. Note that you need to restart Charon as well in order for it to take effect. +::: + +```sh +docker compose down cl-lighthouse +``` + +1. Comment out the currently set `CL` environment variable in `.env` (i.e.: `CL=cl-lighthouse` -> `#CL=cl-lighthouse`). Uncomment the desired CL (i.e.: `#CL=cl-grandine` -> `CL=cl-grandine`). +2. Start the new consensus layer client container. + +```sh +docker compose up cl-grandine -d +``` + +4. Restart Charon in order to update the CL client it's querying. + +```sh +docker compose down charon +docker compose up charon -d +``` + +5. After the new consensus layer client is synced and you are assured the new setup is working, you can delete the previous CL client's data in order to save resources. + +```sh +rm -rf ./data/lighthouse +``` + +### Swap Validator client + +:::info +The code snippets under those steps are assuming you are swapping from Lodestar VC to Teku VC. +::: + +1. Stop the existing validator client container. + +```sh +docker compose down vc-lodestar +``` + +2. Comment out the currently set `VC` environment variable in `.env` (i.e.: `VC=vc-lodestar` -> `#VC=vc-lodestar`). Uncomment the desired VC (i.e.: `#VC=vc-teku` -> `VC=vc-teku`). +3. Start the new validator client container. + +```sh +docker compose up vc-teku -d +``` + +4. After the new validator client is started and you are assured the new setup is working, you can delete the previous VC's data in order to save resources + +```sh +rm -rf ./data/lodestar +``` + +### SWAP MEV client + +:::info +The code snippets under those steps are assuming you are swapping from MEV Boost to Commit Boost and you are using Lighthouse CL. +::: + +:::info +If switching to Commit Boost, you will need to copy a Commit Boost TOML config `commit-boost/config.toml.sample.` to `commit-boost/config.toml`, as it does not support `.env` configurations yet. Make sure the configuration matches what you have had set for mev-boost, in terms of relays and timeouts. +::: + +1. Stop the existing MEV client container. + +```sh +docker compose down mev-mevboost +``` + +2. Comment out the currently set `MEV` environment variable in `.env` (i.e.: `MEV=mev-mevboost` -> `#MEV=mev-mevboost`). Uncomment the desired MEV (i.e.: `#MEV=mev-commitboost` -> `MEV=mev-commitboost`). +3. Start the new MEV client container. + +```sh +docker compose up mev-commitboost -d +``` + +4. Restart the beacon node in order to update the MEV it's querying. + +```sh +docker compose down cl-lighthouse +docker compose up cl-lighthouse -d +``` diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx new file mode 100644 index 0000000000..6a3e28c8a6 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx @@ -0,0 +1,122 @@ +--- +sidebar_label: "Create a DV Using the SDK" +slug: /advanced-and-troubleshooting/advanced/create-a-dv-using-the-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 {#pre-requisites} +* You have [node.js](https://nodejs.org/en) installed. + +### Install the package {#install-the-package} +Install the Obol-SDK package into your development environment + + + +```sh +npm install --save @obolnetwork/obol-sdk +``` + + + +```sh +yarn add @obolnetwork/obol-sdk +``` + + + +### Instantiate the client {#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. + +```sh +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 Hoodi +const obol = new Client({ chainId: 560048 }, signer); +``` + +### Propose the cluster {#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. + +```sh +// 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://hoodi.launchpad.obol.org/dv?configHash=${configHash} to complete the key generation process` +); +``` + +### Invite the Operators to complete the DKG {#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://.launchpad.obol.org/dv?configHash=` and complete the [run a DV with others](../../run-a-dv/start/create-a-dv-with-a-group.mdx) flow. +2. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API. +3. 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 {#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. + +```sh +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 {#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. + +```sh +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 {#usage-examples} +Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples). diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/custom-graffiti.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/custom-graffiti.md new file mode 100644 index 0000000000..bbce0f7cd0 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/custom-graffiti.md @@ -0,0 +1,20 @@ +--- +description: "Add custom graffiti to your block proposals" +sidebar_label: "Custom Graffiti" +slug: /advanced-and-troubleshooting/advanced/custom-graffiti +--- + +# Custom Graffiti + +By default, Charon adds a `charon/-` graffiti to all block proposals. This can be customized using the `--graffiti` and `--graffiti-disable-client-append` CLI flags. + +The `--graffiti` flag accepts either: + +* A single string, which will be used by all validators, or +* A comma-separated list of strings, allowing each validator to have a unique graffiti (one string per validator). + +When possible, Charon automatically appends an Obol signature (`OB`) and the specific consensus client type used (``) to the end of the custom graffiti. This behavior can be disabled by setting the `--graffiti-disable-client-append` flag. + +:::info +The graffiti field in block proposals has a maximum size of 32 bytes. +::: diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/enable-mev.mdx b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/enable-mev.mdx new file mode 100644 index 0000000000..b63202d379 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/enable-mev.mdx @@ -0,0 +1,149 @@ +--- +sidebar_label: "Enable MEV" +slug: /advanced-and-troubleshooting/advanced/enable-mev +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enable MEV + +This quickstart guide focuses on configuring the builder API for Charon and supported validator and consensus clients. + +### Getting started with Charon & the Builder API {#getting-started-with-charon--the-builder-api} +Running a distributed validator cluster with the builder API enabled will give the validators in the cluster access to the builder network. This builder network is a network of "Block Builders" who work with MEV searchers to produce the most valuable blocks a validator can propose. + +[MEV-Boost](https://boost.flashbots.net/) is one such product from Flashbots that enables you to ask multiple block relays (who communicate with the "Block Builders") for blocks to propose. The block that pays the largest reward to the validator will be signed and returned to the relay for broadcasting to the wider network. The end result for the validator is generally an increased APR as they receive some share of the MEV. + +:::info +Before completing this guide, please check your cluster version, which can be found inside the `cluster-lock.json` file. If you are using cluster-lock version `1.7.0` or higher, Charon seamlessly accommodates all validator client implementations within a MEV-enabled distributed validator cluster. + +For clusters with a `cluster-lock.json` version `1.6.0` and below, Charon is compatible only with [Teku](https://github.com/ConsenSys/teku). Use the version history feature of this documentation to see the instructions for configuring a cluster in that manner (`v0.16.0`). +::: + +### Client configuration {#client-configuration} +:::info +You need to add CLI flags to your consensus client, Charon client, and validator client, to enable the builder API. + +You need all operators in the cluster to have their nodes properly configured to use the builder API, or you risk missing a proposal. +::: + +#### Charon {#charon} +Charon supports builder API with the `--builder-api` flag. To use builder API, one simply needs to add this flag to the `charon run` command: + +``` +charon run --builder-api +``` + +#### Consensus Clients {#consensus-clients} +The following flags need to be configured on your chosen consensus client. A Flashbots relay URL is provided for example purposes, you should use the [charon test mev command](../../run-a-dv/prepare/test-a-cluster.mdx#test-mev-relay) and select the two or three relays with the lowest latency to your node that also conform to your block building preferences. A public list of MEV relays is available [here](https://github.com/eth-educators/ethstaker-guides/blob/main/MEV-relay-list.md#mev-relay-list-for-mainnet). + + + +Teku can communicate with a single relay directly: + +``` +teku --builder-endpoint="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +teku --builder-endpoint=http://mev-boost:18550 +``` + + + +Lighthouse can communicate with a single relay directly: + +``` +lighthouse bn --builder="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +Or you can configure it to communicate with a local [MEV-boost](https://github.com/flashbots/mev-boost) sidecar to configure multiple relays: + +``` +lighthouse bn --builder="http://mev-boost:18550" +``` + + + +Prysm can communicate with a single relay directly: + +``` +prysm beacon-chain --http-mev-relay="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +Nimbus can communicate with a single relay directly: + +``` +nimbus_beacon_node \ + --payload-builder=true \ + --payload-builder-url="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + +You should also consider adding `--local-block-value-boost=3` as a flag, to favour locally built blocks if they are withing 3% in value of the relay block, to improve the chances of a successful proposal. + + + +Lodestar can communicate with a single relay directly: + +``` +node ./lodestar --builder --builder.urls="https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net" +``` + + + +#### Validator Clients {#validator-clients} +The following flags need to be configured on your chosen validator client + + + +``` +teku validator-client --validators-builder-registration-default-enabled=true +``` + + + +``` +lighthouse vc --builder-proposals +``` + + + +``` +prysm validator --enable-builder +``` + + + +``` +nimbus_validator_client --payload-builder=true +``` + + + +``` +node ./lodestar validator --builder="true" --builder.selection="builderonly" +``` + + + +### Verify your cluster is correctly configured {#verify-your-cluster-is-correctly-configured} +It can be difficult to confirm everything is configured correctly with your cluster until a proposal opportunity arrives, but here are some things you can check. + +When your cluster is running, you should see if Charon is logging something like this each epoch: + +``` +13:10:47.094 INFO bcast Successfully submitted validator registration to beacon node {"delay": "24913h10m12.094667699s", "pubkey": "84b_713", "duty": "1/builder_registration"} +``` + +This indicates that your Charon node is successfully registering with the relay for a blinded block when the time comes. + +If you are using the [Ultrasound Relay](https://relay.ultrasound.money/), you can enter your cluster's distributed validator public key(s) into their website, to confirm they also see the validator as correctly registered. If you are using [Titan Relay](https://titanrelay.xyz), you can check their API by running `curl https://titanrelay.xyz/relay/v1/data/validator_registration?pubkey=0x123..456` with the public key of a validator in your cluster. + +You should check that your validator client's logs look healthy, and ensure that you haven't added a `fee-recipient` address that conflicts with what has been selected by your cluster in your `cluster-lock.json` file, as that may prevent your validator from producing a signature for the block when the opportunity arises. You should also confirm the same for all of the other peers in your cluster. + +Once a proposal has been made, you should look at the `Block Extra Data` field under `Execution Payload` for the block on [Beaconcha.in](https://beaconcha.in/block/18450364), and confirm there is text present, this generally suggests the block came from a builder, and was not a locally constructed block. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/enable-tls-protocol.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/enable-tls-protocol.md new file mode 100644 index 0000000000..986564914c --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/enable-tls-protocol.md @@ -0,0 +1,38 @@ +--- +description: "Enable the TLS protocol to secure HTTPS requests made by the Validator Client to Charon." +sidebar_label: "Enable TLS Protocol" +slug: /advanced-and-troubleshooting/advanced/enable-tls-protocol +--- + +# Enable TLS Protocol + +## Securing VC to Charon communication + +To secure the communication between the Validator Client and Charon, you can enable the TLS protocol in Charon's HTTP server. This only affects [Beacon API](https://ethereum.github.io/beacon-APIs/) endpoints and not debug/metrics endpoints. As an operator of the node, you need to have a TLS certificate and a private key that signed this certificate or CSR. Then you need to configure Charon to use them. + +## Usage example + +Suppose we don't have a TLS certificate and a key yet. We can create a self-signed certificate and a key using OpenSSL: + +``` +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +Then you could pass the flags to your Charon instance like this: + +``` +charon run --vc-tls-cert-file cert.pem --vc-tls-key-file key.pem +``` + +Charon accepts a certificate in PEM or CRT formats and the private key in PEM or DER formats. + +Also you can specify these parameters as environment variables like this: + +``` +CHARON_VC_TLS_CERT_FILE="cert.pem" +CHARON_VC_TLS_KEY_FILE="key.pem" +``` + +On the Validator Client (VC) side, no additional configuration is typically required. The VC will automatically use the TLS protocol when communicating with Charon. However, if the TLS certificate is signed by a custom or non-standard certificate authority (CA), you may need to configure the VC to trust this CA. This can usually be achieved by adding the CA's certificate to the trusted certificate store on the machine running the VC. + +If necessary, you can also enable `insecure` mode in the VC configuration to bypass TLS verification. Note that this approach is not recommended for production environments as it compromises security. Detailed instructions for configuring specific Validator Clients are beyond the scope of this article. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md new file mode 100644 index 0000000000..8f91a27d84 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/fallback-beacon-nodes.md @@ -0,0 +1,13 @@ +--- +description: "Add fallback beacon nodes to use when primary beacon node fails" +sidebar_label: "Fallback Beacon Nodes" +slug: /advanced-and-troubleshooting/advanced/fallback-beacon-nodes +--- + +# Fallback Beacon Nodes + +Charon allows specifying multiple beacon node URL endpoints. It sends requests to all specified endpoints simultaneously and proceeds with the first response received. This approach improves reliability but increases the load on the beacon nodes. + +To mitigate this additional load, Charon supports configuring a fallback list of beacon nodes. These fallback nodes are only used if all primary beacon nodes fail to respond. This allows operators to designate less critical or public beacon nodes as a backup option, without impacting them under normal conditions. + +To configure fallback beacon nodes, provide a comma-separated list of beacon node URLs using the `--fallback-beacon-node-endpoints` CLI flag. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/nicknames.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/nicknames.md new file mode 100644 index 0000000000..a4cdbb92da --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/nicknames.md @@ -0,0 +1,13 @@ +--- +description: "Add a nickname to your Charon node" +sidebar_label: "Set a Nickname" +slug: /advanced-and-troubleshooting/advanced/nicknames +--- + +# Set a Nickname + +By default, Charon assigns each node a name by combining a random adjective with a random name from a predefined list. While these names are human-readable, they are not easily memorable or personalised for operators. + +You can set a personalised nickname for your Charon node by using the `--nickname` CLI flag followed by the desired string. This nickname is shared with other Charon nodes in the same cluster and included as a label in your Prometheus metrics. + +Nicknames can serve various purposes, such as providing a more memorable identifier, including a Discord ID for alerting, or adding a website URL for publicity. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/operator-rotation.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/operator-rotation.md new file mode 100644 index 0000000000..98e71cd194 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/operator-rotation.md @@ -0,0 +1,107 @@ +--- +description: "Validator consolidation workflow for rotating operators in an Obol distributed validator cluster." +sidebar_label: "Operator Rotation" +slug: /advanced-and-troubleshooting/advanced/operator-rotation +--- + +# Operator Rotation + +### Introduction to Operator Rotation using Pectra Validator Consolidation + +Validator consolidation is a new feature for the Ethereum network, introduced with the last **Pectra** network upgrade. It allows a user to "consolidate" multiple validators into a single, new validator. + +* Consolidations can only be performed when the source validator has 0x01 or 0x02 withdrawal credentials and the target validator must be 0x02. The consolidation transaction must be sent from the withdrawal address defined in the source credentials. The target withdrawal credentials can be any address of choice. +* This process transfers the staked ETH from the old validators to the new one while the stake never leaves the beacon chain. The only partial downtime for the source validator is the standard 27-hour waiting period on the beacon chain before the withdrawal. When compared to fully exiting and re-depositing, consolidation avoids the sweep delay required in that option. + +> \[!NOTE] Future direction (in development): We’re building toward full cluster mutability so operators can react quickly to real-world events. That includes resharing fresh key material across the cluster if there’s ever a security concern, adding new operators to reach full Byzantine fault tolerance, and removing operators who aren’t meeting performance expectations. The goal is to make these changes possible without exiting or consolidating validators. The forthcoming tooling will guide the cluster through a coordinated workflow and produce a fresh set of operator files ready for cutover when you’re comfortable switching over. + +*** + +### Guide: Operator Rotation in an Obol Cluster via Validator Consolidation + +Validator consolidation enables a safe and efficient way to perform operator rotation in an Obol cluster. This is achieved by transferring staked ETH directly from a **source cluster** (source validators with its original operators) to a **target cluster** (target validators with a new set of operators). Operator rotation can be classified into several different scenarios: + +* Source and target cluster validators have the same withdrawal address that is an EOA (wallet address) or a Safe contract. +* Source and target cluster validators have different withdrawal addresses but they are still EOAs. +* Source and target cluster validators have the same OVMs as withdrawal addresses. +* Source and target cluster validators have different OVMs as withdrawal addresses. Source can be an OVM and withdrawal can be an EigenPod/EOA/Safe or vice versa. + +In this guide, we focus on source and target validators that have the same withdrawal address that is an EOA or Safe. The other scenarios are actively in development. + +**Pros:** + +* Compared to the Charon native operator rotation, which requires technical knowledge of node operation, must be executed by operators, and is risky for key security when not done properly, consolidation-based operator rotation can be performed by a withdrawal address (who can be a non-operator such as an ETH allocator). +* Very minimal downtime of \~27 hours (256 epochs) on the stake with source validators. Missed rewards are estimated to be around 0.00296 ETH per validator. + +**Cons:** + +* If the number of validators is very high, even a single day of downtime (even though small) can add up. +* Target validators need to be active. This requires an additional 32 ETH for each target validator the cluster wishes to set up. + +This document outlines the step-by-step process for rotating operators in an Obol DVT cluster using the new validator consolidation feature. This guide assumes you are starting with a source cluster with four existing operators and want to consolidate their validators into a new target cluster with four new operators. + +### 1. Prepare the Target Cluster + +* **Create a New Cluster:** As the user, first create a new Obol cluster for four new operators of your choice. More details can be found [here](../../run-a-dv/start/create-a-dv-with-a-group.mdx). +* **Set Withdrawal Address:** Set the withdrawal address for this new cluster to be the same EOA address you used for the source cluster. In future this can be changed to a withdrawal address of your choice. +* **Deploy a New Splitter:** Deploy a new splitter contract dedicated to the new operators of the target cluster. +* **Configure Validators:** Ensure the validators in the new cluster are configured as **compounding validators** with the `0x02` credential type. To enable this make sure to turn the compound toggle on or use the `--compounding` flag if using the CLI directly. + +![Compounding validator configuration](/img/gitbook/operator-rotation-compounding.png) + +* **Run Nodes:** Start the Charon nodes for all operators in the new target cluster. Make sure all the nodes are healthy and ready for deposits. More details [here](../../run-a-dv/running/monitoring.md). +* **Activate Validators:** Activate the target validators by depositing 32 ETH for each. More details [here](../../run-a-dv/running/activate-a-dv.md). The image shows a new operator `0x493...9b1`. + +![Target validator activation view](/img/gitbook/operator-rotation-activate.png) + +### 2. Finalize the Source Cluster + +* Have a source cluster ready. Make sure you are connected with the correct withdrawal address. In this case, the operator [`0x28eC4c075DF60535DDE5e2788C34B1961c99474c`](https://hoodi.launchpad.obol.org/operator/0x28eC4c075DF60535DDE5e2788C34B1961c99474c/) is also the withdrawal address. + +![Source cluster withdrawal operator](/img/gitbook/operator-rotation-source-withdrawal.png) + +![Source cluster validator list](/img/gitbook/operator-rotation-source-dashboard.png) + +* **Distribute Rewards:** Before proceeding, distribute all pending rewards from the source cluster's splitter contract to ensure all financial obligations are settled with the original operators. The rewards should be 0 after rewards are distributed and claimed. + +![Splitter rewards distribution](/img/gitbook/operator-rotation-rewards.png) + +### 3. Initiate the Consolidation + +* **Access the Migration Tool:** Navigate to the Obol Launchpad migration page by using a URL such as `https://hoodi.launchpad.obol.org/migrate/?withdrawalAddress=your_withdrawal_address`. Alternatively, click the **Migrate** button on a target validator's page within the target cluster dashboard. This **Migrate** button is only clickable for validators where the connected address is the withdrawal address. Make sure the correct address is connected. + +![Launchpad migrate action](/img/gitbook/operator-rotation-migrate.png) + +* **Select Validators:** On the migration page, select the source validators from the original cluster that you wish to consolidate. +* **Confirm and Consolidate:** Click the **Migrate** button to send the consolidation request. + +![Target withdrawal address view](/img/gitbook/operator-rotation-target-withdrawal.png) + +### 4. Post-Consolidation Actions + +> \[!INFO] Screenshots are for reference only, your validator balances and performance will differ. + +* **Source Validator Exit:** Once the consolidation request is processed by the Ethereum network, the source validators will be set to exit automatically. On [beaconcha.in](https://beaconcha.in) the validator pubkey will show an **exiting** status with consolidation in progress. + +![Beaconcha.in validator showing exiting status](/img/gitbook/operator-rotation-beaconcha-exiting.png) + +![Launchpad validator exit notification](/img/gitbook/operator-rotation-launchpad-exit.png) + +* **Waiting Period:** After the exit is complete, the validator enters a \~27 hour waiting period (256 epochs). In the example below the validator is marked **exited** while the withdrawable epoch remains in the future (43257). Once the withdrawable epoch is reached, ETH will be consolidated to the target validator. + +![Beaconcha.in withdrawable epoch countdown](/img/gitbook/operator-rotation-beaconcha-withdrawable.png) + +* **ETH Transfer:** After the waiting period, the staked ETH from the source validators is automatically consolidated and credited to the target validators in the new cluster. + +![Target validator credited after consolidation](/img/gitbook/operator-rotation-target-credited.png) + +* **Wind Down Source Clusters:** Once the source validators have fully exited and funds have settled with the target cluster, you can wind down the original operators. + +![Cluster dashboard ready for wind down](/img/gitbook/operator-rotation-wind-down.png) + +This process ensures a seamless and secure operator rotation, leveraging the efficiency of validator consolidation to minimize downtime and avoid a lengthy manual withdrawal process. + +**Example clusters used in screenshots:** + +* Target cluster: [0x15d1…9e32](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x15d113c8c3e3ca1ec24bbdd5c5d8f9065c36f07d9d70c13e9a4efba8a35b9e32) +* Source cluster: [0xF321…2885](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0xF321443022ABA165FF5635CF71DC9DA0FC29EE91D03117055E97A1F92B5C2885) diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/ovm-predeploy.mdx b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/ovm-predeploy.mdx new file mode 100644 index 0000000000..a64438974e --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/ovm-predeploy.mdx @@ -0,0 +1,904 @@ +--- +description: "Assign pre-created validators to customers on demand" +sidebar_label: "Pre-Create a DV with an OVM" +slug: /advanced-and-troubleshooting/advanced/ovm-predeploy +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Pre-Create a DV with an OVM + +A customer opting into staking at an unknown time, is a key trigger for enterprise staking deployments. There are two primary ways these ad-hoc demands are programatically fulfilled, using smart contracts or using/generating the private keys. + +* Smart contracts such as an [Obol Validator Manager](../../learn/intro/obol-splits.md#obol-validator-managers) (OVM) can re-assign their (beneficial) ownership; allowing a customer to activate a pre-created deposit for this smart contract. +* A fresh DV cluster can be [created](../../run-a-dv/start/create-a-dv-alone.mdx), a [DKG invite](../../run-a-dv/start/create-a-dv-with-a-group.mdx) can be created for waiting [DV-pods](https://github.com/ObolNetwork/helm-charts/tree/main/charts/dv-pod) ready to partake, a [`charon add-validators`](../../run-a-dv/editing/add-validators.md) command could be triggered to add extra keys to a running cluster, or [`charon deposit sign`](alter-withdrawal-addresses.md) could be used to alter an unused validator's withdrawal address. + +This guide will focus on the former, managing validators using Obol smart contracts, and their role based access control. This approach requires less coordination for multi-operator setups, and is simpler than creating or interacting with private key material on the fly by a remote trigger. + +This guide will demonstrate the key steps in preparing a DV cluster for this type of scenario. A blank OVM will be created and assigned validator keys, along with a splitter contract for distributing rewards. Adjust the number of OVMs, splitters, and their key counts for your use case. Administratorship of the OVMs and splitters will be given to a private key that will sit in a secure back end API server, and when a customer triggers an allocation of an OVM, the API server private key will make the necessary updates to an unallocated OVM, and then revoke its control over the smart contracts, leaving them ready for the customer's deposit. + +The Hoodi testnet will be used for all examples. + +![](/img/gitbook/OVMs-on-demand.png) + +:::warning +The following code snippets are minimal examples for the purpose of achieving the desired functionality. These should not be run in production without thorough testing and review. +::: + +#### Pre-requisites + +To keep the `cast` examples neat, we'll declare the key addresses upfront here, and refer to them as environment variables in each `cast` command. + +```sh +# You need an RPC for your commands to reach the Ethereum network. Use one for the correct chain. +export RPC_URL=https://ethereum-hoodi-rpc.publicnode.com +#export RPC_URL=https://ethereum-rpc.publicnode.com + +# This address will be the in case of emergency break glass address for all OVMs. +# This address has custody of the funds and can modify all roles. +# Consider if this address should be the end user, burned outright, +# or a trusted, high threshold SAFE account in case of issue. +export ADMIN_SAFE_ADDRESS=0xFallbackSafeAddressHere + +# The private key corresponding to this address should run in your API service +# This address will have temporary control over the OVM until a User requests it +# Create a keypair with `cast wallet new` and send it some Ether for transaction fees. +export BACKEND_API_ADDRESS=0xPublicAddressForAPIWallet +# The corresponding private key. (Make sure you don't commit it to version control!) +export BACKEND_API_PRIVATE_KEY=0xPrivateKeyForAnAPIWallet + +# The address of the OVM factory on Hoodi +export OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS=0x5754C8665B7e7BF15E83fCdF6d9636684B782b12 +# The address of the OVM factory address on **Mainnet** +#export OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS=0x2c26B5A373294CaccBd3DE817D9B7C6aea7De584 + +# Pull Split Factory Address +export PULL_SPLIT_FACTORY_ADDRESS=0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1 +# https://etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code +``` + +#### Fee Splitting + +A key decision when it comes to preparing a Distributed Validator is how Node Operators and Service providers can be non-custodially compensated for their services. Obol Validator Managers are built to leverage [Splits.org](https://splits.org) split contracts. For this demo, split contracts will be pre-created with the unallocated OVMs, and edited for customers as they appear. You may want to consider smoothing MEV across your customers using a pair of nested splitters. This is described in more detail at the end of the [guide](ovm-predeploy.mdx#appendix-mev-smoothing). + +### Contract Deployment + +A safe and convenient way to deploy an OVM contract is through the [existing contract factory](https://docs.obol.org/next/learn/readme/obol-splits#obol-validator-manager-factory-deployment). A splitter contract can be deployed in a similar fashion. + + + +```sh +# Create a PullSplit owned by the backend API +cast send $PULL_SPLIT_FACTORY_ADDRESS \ + "createSplit((address[],uint256[],uint256,uint16),address,address)" \ + (($BACKEND_API_ADDRESS) (1000000) 1000000, 0) $BACKEND_API_ADDRESS $BACKEND_API_ADDRESS \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY + +# Create an OVM owned by the backend API, with placeholder beneficiary +cast send $OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS \ + "createObolValidatorManager(address,address,address,uint64)" \ + $BACKEND_API_ADDRESS $BACKEND_API_ADDRESS 0xYourRecentlyDeployedPullSplit 16000000000 \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY +``` + + + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +interface IPullSplitFactory { + function createSplit( + SplitParams calldata params, + address owner, + address creator + ) external returns (address split); +} + +struct SplitParams { + address[] recipients; + uint256[] allocations; + uint256 totalAllocation; + uint16 distributionIncentive; +} + +interface IObolValidatorManagerFactory { + function createObolValidatorManager( + address owner, + address beneficiary, + address rewardRecipient, + uint64 principalThreshold + ) external returns (address ovm); +} + +contract DeployOVMAndSplit is Script { + address constant OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS = 0x5754C8665B7e7BF15E83fCdF6d9636684B782b12; + address constant PULL_SPLIT_FACTORY_ADDRESS = 0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1; + address constant BACKEND_API_ADDRESS = 0xPublicAddressForAPIWallet; + + function run() external { + vm.startBroadcast(); + + // Step 1: Deploy the PullSplit via the factory + address[] memory recipients = new address[](1); + recipients[0] = BACKEND_API_ADDRESS; + + uint256[] memory allocations = new uint256[](1); + allocations[0] = 1_000_000; + + address pullSplit = IPullSplitFactory(PULL_SPLIT_FACTORY_ADDRESS).createSplit( + SplitParams({ + recipients: recipients, + allocations: allocations, + totalAllocation: 1_000_000, + distributionIncentive: 0 + }), + BACKEND_API_ADDRESS, // owner + BACKEND_API_ADDRESS // creator + ); + + console.log("PullSplit deployed at:", pullSplit); + + // Step 2: Deploy the OVM via the factory, with the PullSplit as rewardRecipient + address ovm = IObolValidatorManagerFactory(OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS).createObolValidatorManager( + BACKEND_API_ADDRESS, // owner (API wallet) + BACKEND_API_ADDRESS, // beneficiary (placeholder, updated during onboarding) + pullSplit, // rewardRecipient (the PullSplit we just deployed) + 16_000_000_000 // 16 ETH in gwei (recommended principal threshold) + ); + + console.log("ObolValidatorManager deployed at:", ovm); + + vm.stopBroadcast(); + } +} +``` + + + +```ts +import { + createWalletClient, + createPublicClient, + http, + parseAbi, + parseEventLogs, +} from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { hoodi } from "viem/chains"; + +// Factory contract addresses (already deployed) +const OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS = "0x5754C8665B7e7BF15E83fCdF6d9636684B782b12"; +const PULL_SPLIT_FACTORY_ADDRESS = "0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1"; + +const BACKEND_API_ADDRESS = "0xPublicAddressForAPIWallet"; + +// Minimal ABIs for the factories +const splitFactoryAbi = parseAbi([ + "function createSplit((address[],uint256[],uint256,uint16),address,address) external returns (address split)", +]); + +const ovmFactoryAbi = parseAbi([ + "function createObolValidatorManager(address owner, address beneficiary, address rewardRecipient, uint64 principalThreshold) external returns (address ovm)", + "event CreateObolValidatorManager(address indexed ovm, address indexed owner, address beneficiary, address rewardRecipient, uint64 principalThreshold)", +]); + +// Set up account from private key (the backend API key) +const account = privateKeyToAccount("0x..."); + +const walletClient = createWalletClient({ + account, + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +const publicClient = createPublicClient({ + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +// Step 1: Deploy the PullSplit via the factory +const splitHash = await walletClient.writeContract({ + address: PULL_SPLIT_FACTORY_ADDRESS, + abi: splitFactoryAbi, + functionName: "createSplit", + args: [ + { + recipients: [BACKEND_API_ADDRESS], + allocations: [1_000_000n], + totalAllocation: 1_000_000n, + distributionIncentive: 0, + }, + BACKEND_API_ADDRESS, // owner + BACKEND_API_ADDRESS, // creator + ], +}); + +console.log("PullSplit deploy tx:", splitHash); +const splitReceipt = await publicClient.waitForTransactionReceipt({ hash: splitHash }); + +// Extract the PullSplit address from the transaction logs +// (adjust based on the factory's event signature) +const pullSplitAddress = splitReceipt.logs[0].address; +console.log("PullSplit deployed at:", pullSplitAddress); + +// Step 2: Deploy the OVM via the factory, with the PullSplit as rewardRecipient +const ovmHash = await walletClient.writeContract({ + address: OBOL_VALIDATOR_MANAGER_FACTORY_ADDRESS, + abi: ovmFactoryAbi, + functionName: "createObolValidatorManager", + args: [ + BACKEND_API_ADDRESS, // owner (API wallet) + BACKEND_API_ADDRESS, // beneficiary (placeholder, updated during onboarding) + pullSplitAddress, // rewardRecipient (the PullSplit we just deployed) + 16_000_000_000n, // 16 ETH in gwei (recommended principal threshold) + ], +}); + +console.log("OVM deploy tx:", ovmHash); +const ovmReceipt = await publicClient.waitForTransactionReceipt({ hash: ovmHash }); + +const logs = parseEventLogs({ + abi: ovmFactoryAbi, + logs: ovmReceipt.logs, + eventName: "CreateObolValidatorManager", +}); + +const ovmAddress = logs[0].args.ovm; +console.log("ObolValidatorManager deployed at:", ovmAddress); +``` + + + +After you have deployed an Obol Validator Manager contract, let's save its address and an example customer address as environment variables to make the rest of the `cast` demo easier. + +```sh +# The created OVM from the factory +export EXAMPLE_OVM_ADDRESS=0xYourRecentlyDeployedOVM + +# The created PullSplit from the factory +export EXAMPLE_PULL_SPLIT_ADDRESS=0xYourRecentlyDeployedPullSplit + +# An address of a hypothetical new customer +export EXAMPLE_CUSTOMER_ADDRESS=0xCustomerAddress + +# A private key of a new customer. (Demo Only. Don't use raw customer private keys in practice) +export EXAMPLE_CUSTOMER_PRIVATE_KEY=0xCustomerPrivateKey +``` + +### Create the DV Cluster + +At this point, you can prepare a DV cluster pointed at these OVMs and split contracts. Use the [`charon create cluster ... --publish`](../../learn/charon/charon-cli-reference.md#create-a-full-cluster-locally) command if you are controlling the validator keys centrally, or [`charon create dkg ... ---publish`](../../learn/charon/charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) if you have a group of operators taking part in the cluster. Comma separate the `--withdrawal-addresses` and `--fee-recipient-addresses` flags with your created OVMs and Pull Splits. Once you complete the key creation, you can load these artifacts into your nodes and get the cluster online and ready for deposits. At this point the last remaining action will be with the API key, which will change the ownership of an OVM to make it ready for deposits. + +### Assigning the Contracts to Customers + +When a capital allocator (customer) is onboarding, the pre-created contracts can be assigned to that entity. The principal beneficiary address is updated to the entity's preferred address, permissions are allocated to the customer and backend's addresses as needed, and then ownership of the OVMs are transferred or burned. + + + +```sh +# Set the beneficiary address to the customer +cast send $EXAMPLE_OVM_ADDRESS \ + "setBeneficiary(address)" \ + $EXAMPLE_CUSTOMER_ADDRESS \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY + +# Modify the splitter to include the customer and service providers (example is 90/10 split customer/admin address) +cast send $EXAMPLE_PULL_SPLIT_ADDRESS \ + "updateSplit(address[],uint256[],uint256,uint16)" \ + ($EXAMPLE_CUSTOMER_ADDRESS,$ADMIN_SAFE_ADDRESS) (900000,100000) 1000000 0 \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY + +# Grant the customer the DEPOSIT_ROLE and WITHDRAWAL_ROLE +cast send $EXAMPLE_OVM_ADDRESS \ + "grantRoles(address,uint256)" \ + $EXAMPLE_CUSTOMER_ADDRESS 21 \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY + +# [OPTIONAL] If the backend service needs the ability to trigger +# partial (or full) withdrawals, grant it the WITHDRAWAL_ROLE. +# Warning; This allows this address to selectively charge fees on principal +cast send $EXAMPLE_OVM_ADDRESS \ + "grantRoles(address,uint256)" \ + $BACKEND_API_ADDRESS 1 \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY +``` + + + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +interface IObolValidatorManager { + function setBeneficiary(address newBeneficiary) external; + function grantRoles(address user, uint256 roles) external payable; +} + +interface IPullSplit { + function updateSplit( + address[] calldata recipients, + uint256[] calldata allocations, + uint256 totalAllocation, + uint16 distributionIncentive + ) external; +} + +contract AssignToCustomer is Script { + address constant OVM_ADDRESS = 0xYourOVMAddress; + address constant PULL_SPLIT_ADDRESS = 0xYourPullSplitAddress; + address constant CUSTOMER_ADDRESS = 0xCustomerAddress; + address constant ADMIN_SAFE_ADDRESS = 0xFallbackSafeAddressHere; + + uint256 constant WITHDRAWAL_ROLE = 0x01; + uint256 constant DEPOSIT_ROLE = 0x20; + + function run() external { + vm.startBroadcast(); + + IObolValidatorManager ovm = IObolValidatorManager(OVM_ADDRESS); + + // Set the beneficiary to the customer address + ovm.setBeneficiary(CUSTOMER_ADDRESS); + console.log("Beneficiary set to:", CUSTOMER_ADDRESS); + + // Update the splitter to include the customer and service providers (90/10 split) + address[] memory recipients = new address[](2); + recipients[0] = CUSTOMER_ADDRESS; + recipients[1] = ADMIN_SAFE_ADDRESS; + + uint256[] memory allocations = new uint256[](2); + allocations[0] = 900_000; + allocations[1] = 100_000; + + IPullSplit(PULL_SPLIT_ADDRESS).updateSplit(recipients, allocations, 1_000_000, 0); + console.log("PullSplit updated with customer and service provider shares"); + + // Grant the customer deposit and withdrawal roles + ovm.grantRoles(CUSTOMER_ADDRESS, WITHDRAWAL_ROLE | DEPOSIT_ROLE); + console.log("Customer assigned deposit and withdrawal roles"); + + vm.stopBroadcast(); + } +} +``` + + + +```ts +import { createWalletClient, createPublicClient, http, parseAbi } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { hoodi } from "viem/chains"; + +// The deployed OVM and PullSplit addresses +const OVM_ADDRESS = "0xYourOVMAddress"; +const PULL_SPLIT_ADDRESS = "0xYourPullSplitAddress"; + +// The customer address to receive principal deposits +const CUSTOMER_ADDRESS = "0xCustomerAddress"; + +// Admin safe for service provider fee share +const ADMIN_SAFE_ADDRESS = "0xFallbackSafeAddressHere"; + +// Role bitmasks from the contract +const WITHDRAWAL_ROLE = 0x01n; +const DEPOSIT_ROLE = 0x20n; + +// Combine roles using bitwise OR +const ROLES_TO_GRANT = WITHDRAWAL_ROLE | DEPOSIT_ROLE; // 0x21 + +const ovmAbi = parseAbi([ + "function setBeneficiary(address newBeneficiary) external", + "function grantRoles(address user, uint256 roles) external payable", +]); + +const pullSplitAbi = parseAbi([ + "function updateSplit(address[],uint256[],uint256,uint16) external", +]); + +// Use the backend API key +const account = privateKeyToAccount("0xBackendAPIPrivateKey..."); + +const walletClient = createWalletClient({ + account, + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +const publicClient = createPublicClient({ + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +// Step 1: Set the beneficiary to the customer address +const hash1 = await walletClient.writeContract({ + address: OVM_ADDRESS, + abi: ovmAbi, + functionName: "setBeneficiary", + args: [CUSTOMER_ADDRESS], +}); + +console.log("Set beneficiary tx:", hash1); +await publicClient.waitForTransactionReceipt({ hash: hash1 }); +console.log("Beneficiary set to:", CUSTOMER_ADDRESS); + +// Step 2: Update the splitter to include customer and service providers (90/10 split) +const hash2 = await walletClient.writeContract({ + address: PULL_SPLIT_ADDRESS, + abi: pullSplitAbi, + functionName: "updateSplit", + args: [ + [CUSTOMER_ADDRESS, ADMIN_SAFE_ADDRESS], + [900_000n, 100_000n], + 1_000_000n, + 0, + ], +}); + +console.log("Update split tx:", hash2); +await publicClient.waitForTransactionReceipt({ hash: hash2 }); +console.log("PullSplit updated with customer and service provider shares"); + +// Step 3: Grant the customer deposit and withdrawal roles +const hash3 = await walletClient.writeContract({ + address: OVM_ADDRESS, + abi: ovmAbi, + functionName: "grantRoles", + args: [CUSTOMER_ADDRESS, ROLES_TO_GRANT], +}); + +console.log("Grant roles tx:", hash3); +await publicClient.waitForTransactionReceipt({ hash: hash3 }); +console.log("Deposit and withdrawal role assigned to customer"); +``` + + + +### Transferring Ownership + +:::warning +This is a crucial step, and failure to adequately secure the ownership of an OVM could lead to a loss or theft of funds. Ensure you trust the `owner()` address of an OVM before making a deposit. +::: + +The last step before the OVM is ready for activation is to transfer the ownership of the OVM away from the backend, to either the customer, or an extremely well secured administrative multi-sig wallet like a [SAFE](https://safe.global) that can intervene to update key values in future if needed. Consider that the owner of an OVM has custodial control over it. + + + +```sh +cast send $EXAMPLE_OVM_ADDRESS \ + "transferOwnership(address)" \ + $ADMIN_SAFE_ADDRESS \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY +``` + + + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +interface IObolValidatorManager { + function transferOwnership(address newOwner) external payable; +} + +contract TransferOwnership is Script { + address constant OVM_ADDRESS = 0xYourOVMAddress; + address constant SAFE_ADDRESS = 0xYourSafeAddress; + + function run() external { + vm.startBroadcast(); + + IObolValidatorManager(OVM_ADDRESS).transferOwnership(SAFE_ADDRESS); + + console.log("Ownership transferred to SAFE:", SAFE_ADDRESS); + + vm.stopBroadcast(); + } +} +``` + + + +```ts +import { createWalletClient, createPublicClient, http, parseAbi } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { hoodi } from "viem/chains"; + +// The deployed OVM address +const OVM_ADDRESS = "0xYourOVMAddress"; + +// The SAFE wallet address to transfer ownership to +const SAFE_ADDRESS = "0xYourSafeAddress"; + +const ovmAbi = parseAbi([ + "function transferOwnership(address newOwner) external payable", +]); + +// The backend API address that currently owns the OVM +const account = privateKeyToAccount("0x..."); + +const walletClient = createWalletClient({ + account, + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +const publicClient = createPublicClient({ + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +// Transfer ownership to the SAFE +const hash = await walletClient.writeContract({ + address: OVM_ADDRESS, + abi: ovmAbi, + functionName: "transferOwnership", + args: [SAFE_ADDRESS], +}); + +console.log("Transfer ownership tx:", hash); +await publicClient.waitForTransactionReceipt({ hash: hash }); + +console.log("Ownership transferred to SAFE:", SAFE_ADDRESS); +``` + + + +### Handling Deposits + +The capital allocator can now deposit the validators that point to this withdrawal address. The validator keys are held by the [provisioned DV cluster](../../run-a-dv/start/) operators and the deposit data was created during cluster creation. + +This step would normally be through a wallet and web interface. This example using raw private keys is for demo purposes only. + +:::info +To accurately differentiate reward from principal in an OVM, the OVM contract needs to be invoked during the deposit call. Each OVM has a `deposit()` function exactly matching and wrapping the official deposit smart contract, and should be used for that purpose. + +If a deposit is made not through the OVM, the OVM can be updated with the `setAmountOfPrincipalStake()` method by the `owner` or an address with the `SET_BENEFICIARY_ROLE`. +::: + + + +```sh +cast send $EXAMPLE_OVM_ADDRESS \ + "deposit(bytes,bytes,bytes,bytes32)" \ + 0x \ + 0x \ + 0x \ + 0x \ + --value 32ether \ + --rpc-url $RPC_URL \ + --private-key $EXAMPLE_CUSTOMER_PRIVATE_KEY +``` + + + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +interface IObolValidatorManager { + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) external payable; +} + +contract Deposit is Script { + address constant OVM_ADDRESS = 0xYourOVMAddress; + + function run() external { + // Deposit data (parsed from deposit-data.json) + bytes memory pubkey = hex"..."; // 48 bytes + bytes memory withdrawal_credentials = hex"..."; // 32 bytes + bytes memory signature = hex"..."; // 96 bytes + bytes32 deposit_data_root = hex"..."; // 32 bytes + + vm.startBroadcast(); + + // Deposit 32 ETH to activate a validator + IObolValidatorManager(OVM_ADDRESS).deposit{value: 32 ether}( + pubkey, + withdrawal_credentials, + signature, + deposit_data_root + ); + + console.log("Deposit complete - validator activation pending"); + + vm.stopBroadcast(); + } +} +``` + + + +```ts +import { createWalletClient, createPublicClient, http, parseAbi } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { hoodi } from "viem/chains"; + +// The deployed OVM address +const OVM_ADDRESS = "0xYourOVMAddress"; + +// Deposit data (parsed from deposit-data.json) +const pubkey = "0x..."; // 48 bytes +const withdrawal_credentials = "0x..."; // 32 bytes +const signature = "0x..."; // 96 bytes +const deposit_data_root = "0x..."; // 32 bytes + +const ovmAbi = parseAbi([ + "function deposit(bytes calldata pubkey, bytes calldata withdrawal_credentials, bytes calldata signature, bytes32 deposit_data_root) external payable", +]); + +// Use the customer key (has DEPOSIT_ROLE), normally do this via wallet connection +const account = privateKeyToAccount("0xCustomerPrivateKey..."); + +const walletClient = createWalletClient({ + account, + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +const publicClient = createPublicClient({ + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +// Deposit 32 ETH to activate a validator +const hash = await walletClient.writeContract({ + address: OVM_ADDRESS, + abi: ovmAbi, + functionName: "deposit", + args: [pubkey, withdrawal_credentials, signature, deposit_data_root], + value: 32_000_000_000_000_000_000n, // 32 ETH in wei +}); + +console.log("Deposit tx:", hash); +await publicClient.waitForTransactionReceipt({ hash: hash }); +console.log("Deposit complete - validator activation pending"); +``` + + + +The validator(s) will enter the activation queue and the `amountOfPrincipalStake` value on the contract will track how much of the balance is considered the principal (owed to the beneficiary). The EL and CL rewards from any targeting validators will be sent to the OVM contract and Pull Split. + +### Withdrawing Validator Balance + +Compounding validators (0x02 type) can have part of their principal withdrawn from active stake, or be fully exited, via the same `withdraw()` call. Specifying a nonzero value for `amounts` will initiate a partial withdrawal, while 0 will fully exit the validator. You cannot specify an amount that will leave the validator with less than 32 ether in active stake remaining. + +:::warning +There is an important nuance when it comes to partial withdrawals. With an OVM (on the default settings), it will treat a withdrawal of less than 16 ether as rewards rather than principal. **A customer should not withdraw less than this amount of principal or they may be charged fees on it**. Similarly, care must be taken with the `WITHDRAWAL_ROLE`; although it does not allow the changing of who gets rewards, it can cause this 'over-charging' behaviour by doing repeated small withdrawals. +::: + + + +```sh +cast send $EXAMPLE_OVM_ADDRESS \ + "withdraw(bytes[],uint64[],uint256,address)" \ + "[0x]" \ + "[16000000000]" \ + 1000000000000000 \ + 0xYourRefundAddress \ + --value 0.001ether \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY +``` + + + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +interface IObolValidatorManager { + function withdraw( + bytes[] calldata pubKeys, + uint64[] calldata amounts, + uint256 maxFeePerWithdrawal, + address excessFeeRecipient + ) external payable; +} + +contract PartialWithdrawal is Script { + address constant OVM_ADDRESS = 0xYourOVMAddress; + + // Validator public key (48 bytes) + bytes constant VALIDATOR_PUBKEY = hex"abc123YourValidatorPubkey"; + + // Amount to withdraw in gwei (16 ETH) + uint64 constant WITHDRAWAL_AMOUNT = 16_000_000_000; + + // Maximum fee willing to pay per withdrawal request + uint256 constant MAX_FEE_PER_WITHDRAWAL = 0.001 ether; + + function run() external { + vm.startBroadcast(); + + bytes[] memory pubKeys = new bytes[](1); + pubKeys[0] = VALIDATOR_PUBKEY; + + uint64[] memory amounts = new uint64[](1); + amounts[0] = WITHDRAWAL_AMOUNT; + + IObolValidatorManager(OVM_ADDRESS).withdraw{value: MAX_FEE_PER_WITHDRAWAL}( + pubKeys, + amounts, + MAX_FEE_PER_WITHDRAWAL, + msg.sender // Excess fee refunded here + ); + + console.log("Partial withdrawal requested for 16 ETH"); + + vm.stopBroadcast(); + } +} +``` + + + +```ts +import { createWalletClient, createPublicClient, http, parseAbi } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { hoodi } from "viem/chains"; + +// The deployed OVM address +const OVM_ADDRESS = "0xYourOVMAddress"; + +// Validator public key (48 bytes) +const VALIDATOR_PUBKEY = "0xabc123YourValidatorPubkey"; + +// Amount to withdraw in gwei (16 ETH = 16,000,000,000 gwei) +const WITHDRAWAL_AMOUNT = 16_000_000_000n; + +// Maximum fee willing to pay per withdrawal request +const MAX_FEE_PER_WITHDRAWAL = 1_000_000_000_000_000n; // 0.001 ETH + +const ovmAbi = parseAbi([ + "function withdraw(bytes[] calldata pubKeys, uint64[] calldata amounts, uint256 maxFeePerWithdrawal, address excessFeeRecipient) external payable", +]); + +// Use the secondary key (has WITHDRAWAL_ROLE) +const account = privateKeyToAccount("0xSecondaryKeyPrivateKey..."); + +const walletClient = createWalletClient({ + account, + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +const publicClient = createPublicClient({ + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +// Request partial withdrawal of 16 ETH +const hash = await walletClient.writeContract({ + address: OVM_ADDRESS, + abi: ovmAbi, + functionName: "withdraw", + args: [ + [VALIDATOR_PUBKEY], + [WITHDRAWAL_AMOUNT], + MAX_FEE_PER_WITHDRAWAL, + account.address, // Excess fee refunded here + ], + value: MAX_FEE_PER_WITHDRAWAL, // Send enough to cover the fee +}); + +console.log("Partial withdrawal tx:", hash); +await publicClient.waitForTransactionReceipt({ hash: hash }); +console.log( + "Partial withdrawal requested - funds will arrive after protocol processes it" +); +``` + + + +### Reward Distribution and Splitters + +When withdrawals requested eventually exit the beacon chain, they appear on the OVM contract, and should be distributed to the `rewardRecipient` or `principalRecipient` (depending on if they amount to above or below the `principalThreshold` of 16 eth). Calling `distributeFunds()` will push the Ether to the correct address. Split contracts as principal or reward addresses will also need to be distributed from for the funds to land in their ultimate recipients addresses. + + + +```sh +cast send $EXAMPLE_OVM_ADDRESS \ + "distributeFunds()" \ + --rpc-url $RPC_URL \ + --private-key $BACKEND_API_PRIVATE_KEY +``` + + + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +interface IObolValidatorManager { + function distributeFunds() external; +} + +contract DistributeFunds is Script { + address constant OVM_ADDRESS = 0xYourOVMAddress; + + function run() external { + vm.startBroadcast(); + + IObolValidatorManager(OVM_ADDRESS).distributeFunds(); + console.log("Funds distributed to beneficiary and reward recipient"); + + vm.stopBroadcast(); + } +} +``` + + + +```ts +import { createWalletClient, createPublicClient, http, parseAbi } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { hoodi } from "viem/chains"; + +// The deployed OVM address +const OVM_ADDRESS = "0xYourOVMAddress"; + +const ovmAbi = parseAbi(["function distributeFunds() external"]); + +// Anyone can call distributeFunds - no special role required +const account = privateKeyToAccount("0x..."); + +const walletClient = createWalletClient({ + account, + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +const publicClient = createPublicClient({ + chain: hoodi, + transport: http("https://ethereum-hoodi-rpc.publicnode.com"), +}); + +// Distribute funds to beneficiary (principal) and rewardRecipient (rewards) +const hash = await walletClient.writeContract({ + address: OVM_ADDRESS, + abi: ovmAbi, + functionName: "distributeFunds", +}); + +console.log("Distribute funds tx:", hash); +await publicClient.waitForTransactionReceipt({ hash: hash }); +console.log("Funds distributed to beneficiary and reward recipient"); +``` + + + +#### Appendix: MEV Smoothing + +If you setup validators where every customer gets their own fee recipient address (and underlying splitter), they will each get proposals rarely (approximately twice per year for a 32 ETH validator). Due to MEV being unequally distributed, only a small number of proposals in the year contain most of the MEV. This means that most of your users will get the median amount of Ether as MEV rather than the average, and may notice a lower APR versus setups that pool and distribute their variable rewards across their users. It may be beneficial for you to instead smooth the MEV being accrued through block proposals across all depositors in the cluster. This can be achieved through two nested split contracts as follows: + +* First create an editable [PullSplit](https://docs.splits.org/core/split-v2) we'll refer to as the Child Split. The owner of this split should be the `$BACKEND_API_ADDRESS`. +* Next create a second PullSplit we'll refer to as the Parent Split. It can be immutable if preferred. It should send the majority of its inflow to the Child Split, and some amount to a set of addresses that receive operating fees for the cluster. +* Set the parent split as the `--fee-recipient-address` for all validators in the cluster. This means all proposal rewards for the cluster will go to this address. +* When a customer makes a deposit, use the `$BACKEND_API_PRIVATE_KEY` to update the Child Split to proportionally reflect the eth provided by all customers to the cluster. +* As proposals by the validators earn tips and MEV, this collects on the Split Contracts. Distributing these rewards sends the ether to the fee recipients and customers. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/partial-deposit.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/partial-deposit.md new file mode 100644 index 0000000000..e40d18f37d --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/partial-deposit.md @@ -0,0 +1,64 @@ +--- +description: "Submit and fetch (partial) deposits." +sidebar_label: "The need of partial deposits" +slug: /advanced-and-troubleshooting/advanced/partial-deposit +unlisted: true +--- + +# The need of partial deposits + +Some operators opt to create a big cluster, even though only a subset of the validators will be activated in the short term. +When there is enough business incentive to activate more validators from the cluster, the business cases might have changed and a different withdrawal addresses to be required for those new validators. + +Changing the signed deposit data post- cluster creation and pre- validator activation can be useful in such scenarios. Threshold of nodes need to agree and sign the new deposit data, then the signatures are aggregated and the new deposit data message is created. For convenience, Obol API is used for that purpose. + +## Sign partial deposit data + +First a partial deposit data signature from the current Charon node should be signed and broadcasted to Obol API. + +`validator-public-keys` are the validator public keys for which the new deposit data should be signed. +`withdrawal-addresses` are the new addresses for which the new deposit data should be signed. They should either be the same amount as `validator-public-keys` or a single one, that will be used for all keys. +Optionally, users can also specify different multiple `deposit-amounts` (defaults to only `32`). + +**Single public key** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0x0100000000000000000000000d941218c10b055f0907fe1bbe486ccdaa7e332b" +``` + +**Multiple public keys, multiple withdrawal addresses** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0x0100000000000000000000000d941218c10b055f0907fe1bbe486ccdaa7e332b,0x0100000000000000000000000e941218c10b055f0907fe1bbe486ccdaa7e332b" +``` + +**Multiple public keys, single withdrawal address** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit sign \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ + --withdrawal-addresses="0x0100000000000000000000000d941218c10b055f0907fe1bbe486ccdaa7e332b" +``` + +## Fetch full deposit data + +After a threshold of operators have submitted partial deposits, a full deposit can be fetched from Obol API. + +`validator-public-keys` are the validator public keys for which the new deposit data should be fetched. + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 deposit fetch \ + --validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \ +``` + +After a successful fetch the new deposit data files are saved in `.charon/deposit-data-`. + +If there are not enough partial signatures, an error message will be returned. + +```sh +17:18:40.771 ERRO cmd Application failed to start: fetch full deposit data from Obol API: not enough partial signatures to meet threshold {"submitted_public_keys": "[0x8677e2014a173f72b3d4528893cb01881549631c2a39d90d7c19c230299a57440e73c82c7daf1d72713b1e26e42bae99]", "submitted_public_keys_length": 1, "required_threshold": 3} +``` diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/quickstart-combine.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/quickstart-combine.md new file mode 100644 index 0000000000..a453a6a782 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/quickstart-combine.md @@ -0,0 +1,112 @@ +--- +description: "Combine distributed validator private key shares to recover the validator private key." +sidebar_label: "Combine DV Private Key Shares" +slug: /advanced-and-troubleshooting/advanced/quickstart-combine +--- + +# 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.9.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. +::: diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/quickstart-split.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/quickstart-split.md new file mode 100644 index 0000000000..573ad9c7a8 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/quickstart-split.md @@ -0,0 +1,110 @@ +--- +description: "Migrate an existing validator by splitting its private key into shares" +sidebar_label: "Migrate an Existing Validator" +slug: /advanced-and-troubleshooting/advanced/quickstart-split +--- + +# Migrate an Existing Validator + +:::warning +This process should only be used if you want to split an _existing validator private key_ into multiple private key shares for use in a Distributed Validator Cluster. **If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed**. + +If you are starting a new validator, you should follow a [quickstart guide](../../run-a-dv/start/quickstart_overview.md) instead. +::: + +Split an existing Ethereum validator key into multiple key shares for use in an [Obol Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +## Pre-requisites + +* Ensure you have the existing validator keystores (the ones to split) and passwords. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. +* If you use MEV-Boost, you must either: + * Turn off your MEV-Boost client before you split your keys, or; + * Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting. + +## Step 1. Prepare the existing keystore files + +:::info +Starting with Charon v1.8.0, you may not need to manually prepare the keystore files as described below. Charon can recursively search for keystore files in the specified directory and attempt to match the corresponding password files. The only case where this does not work is when you specify an exact list of withdrawal addresses; in that case, you must prepare the files manually and ensure the keystore indices match the order of the specified withdrawal addresses. +::: + +Create a folder to hold the encrypted keystores, along with the passwords to decrypt them. + +```shell + # Create a folder + mkdir split_keys +``` + +Copy the existing validator `keystore.json` files into this new folder. Alongside them, with a matching filename but ending with `.txt` should be the password to the keystore (e.g.: `keystore-0.json`, `keystore-0.txt`). The files must start with `keystore*`. + +At the end of this process, you should have a tree like this: + +```shell +├── split_keys +│   ├── keystore-0.json +│   ├── keystore-0.txt +│   ├── keystore-1.json +│   ├── keystore-1.txt +│ ... +│   ├── keystore-N.json +│   ├── keystore-N.txt +``` + +## Step 2. Split the keys using the charon docker command + +Run the following docker command to split the keys (for mainnet): + +```shell +CHARON_VERSION= # E.g. v1.9.0 +CLUSTER_NAME= # The name of the cluster you want to create. +WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited) +FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments. +NODES= # The number of nodes in the cluster. + +docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \ + --name="${CLUSTER_NAME}" \ + --withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \ + --fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \ + --split-existing-keys \ + --split-keys-dir=/opt/charon/split_keys \ + --nodes ${NODES} \ + --network mainnet \ + --publish +``` + +The above command will create `validator_keys` along with `cluster-lock.json` in `./cluster` for each node. + +Command output: + +```shell +***************** WARNING: Splitting keys ********************** + Please make sure any existing validator has been shut down for + at least 2 finalised epochs before starting the Charon cluster, + otherwise slashing could occur. +**************************************************************** + +Created Charon cluster: + --split-existing-keys=true + +./cluster/ +├─ node[0-*]/ # Directory for each node +│ ├─ charon-enr-private-key # Charon networking private key for node authentication +│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes +│ ├─ validator_keys # Validator keystores and password +│ │ ├─ keystore-*.json # Validator private share key for duty signing +│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json +``` + +These split keys can now be used to start a Charon cluster. + +## Step 3. (Optional) Encrypt artifacts for distribution + +Within each folder are the encrypted [private key shares](../../learn/intro/key-concepts.md#distributed-validator-key-share), along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a `.zip` to transport them. + +```shell +# For each folder in ./cluster/ encrypt it with a different password +zip -er node1.zip ./cluster/node1/ + +# Repeat for node2,...,nodeN. +``` diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/self-relay.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/self-relay.md new file mode 100644 index 0000000000..a760a0d05d --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/advanced/self-relay.md @@ -0,0 +1,50 @@ +--- +description: "Self-host a relay" +sidebar_label: "Self-Host a Relay" +slug: /advanced-and-troubleshooting/advanced/self-relay +--- + +# Self-Host a Relay + +If you are experiencing connectivity issues with the Obol hosted relays, or you want to improve your clusters latency, resilience, and decentralization, you can opt to host your own relay on a separate open and static internet port. + +Below is a simple `docker compose` file which runs a Charon as a relay server: + +```shell +# Clone the repo and cd into it. +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git + +cd charon-distributed-validator-node + +# If you are exposing your relay on the public internet, determine your public IP +curl v4.ident.me + +# Replace 'replace.with.public.ip.or.hostname' in relay/docker-compose.yml with your +# public IPv4 or DNS hostname, or with your private IP on your local (v)LAN, if this +# relay is running for Charon's sharing a private network. +nano relay/docker-compose.yml + +# Start the relay +docker compose -f relay/docker-compose.yml up +``` + +Test whether the relay is publicly (or privately) accessible. This should return an ENR: `curl http://replace.with.public.ip.or.hostname:3640/enr` + +Ensure the ENR returned by the relay contains the correct public IP and port by decoding it with [ENR viewer](https://enr-viewer.com/). + +Configure **ALL** charon nodes in your cluster to use this relay: + +* Either by adding a flag: `--p2p-relays=http://replace.with.public.ip.or.hostname:3640/enr` +* Or by setting the environment variable: `CHARON_P2P_RELAYS=http://replace.with.public.ip.or.hostname:3640/enr` + +:::info +Keep the default relays and append your self-hosted relay to Charon's flag/environment variables if you want the most resilience `https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev`, rather than having your one relay be a single point of failure in your cluster. +::: + +:::info +If you are running a relay on a private network, consult your monitoring to confirm your Charon nodes are able to establish a direct connection with one another for optimal performance. You may need to update `charon run` to specify `--p2p-tcp-address= + +I would recommend removing the ability to use a non-ETH token from the `OptimisticWithdrawalRecipient`. Alternatively, if it feels like it may be a use case that is needed, it may make sense to always include ETH as a valid token, in addition to any `OWRToken` set. + +**Review** + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[M-02] Splits with 256 or more node operators will not be able to switch on fees[​](smart-contract-audit.md#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees) {#m-02-splits-with-256-or-more-node-operators-will-not-be-able-to-switch-on-fees} +0xSplits is used to distribute rewards across node operators. All Splits are deployed with an ImmutableSplitController, which is given permissions to update the split one time to add a fee for Obol at a future date. + +The Factory deploys these controllers as Clones with Immutable Args, hard coding the `owner`, `accounts`, `percentAllocations`, and `distributorFee` for the future update. This data is packed as follows: + +```solidity + function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee + ) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; + uint256[] memory recipients = new uint[](recipientsSize); + + uint256 i = 0; + for (; i < recipientsSize;) { + recipients[i] = (uint256(percentAllocations[i]) << ADDRESS_BITS) | uint256(uint160(accounts[i])); + + unchecked { + i++; + } + } + + data = abi.encodePacked(splitMain, distributorFee, owner, uint8(recipientsSize), recipients); + } +``` + +In the process, `recipientsSize` is unsafely downcasted into a `uint8`, which has a maximum value of `256`. As a result, any values greater than 256 will overflow and result in a lower value of `recipients.length % 256` being passed as `recipientsSize`. + +When the Controller is deployed, the full list of `percentAllocations` is passed to the `validSplit` check, which will pass as expected. However, later, when `updateSplit()` is called, the `getNewSplitConfiguation()` function will only return the first `recipientsSize` accounts, ignoring the rest. + +```solidity + function getNewSplitConfiguration() + public + pure + returns (address[] memory accounts, uint32[] memory percentAllocations) + { + // fetch the size first + // then parse the data gradually + uint256 size = _recipientsSize(); + accounts = new address[](size); + percentAllocations = new uint32[](size); + + uint256 i = 0; + for (; i < size;) { + uint256 recipient = _getRecipient(i); + accounts[i] = address(uint160(recipient)); + percentAllocations[i] = uint32(recipient >> ADDRESS_BITS); + unchecked { + i++; + } + } + } +``` + +When `updateSplit()` is eventually called on `splitsMain` to turn on fees, the `validSplit()` check on that contract will revert because the sum of the percent allocations will no longer sum to `1e6`, and the update will not be possible. + +**Proof of Concept** + +The following test can be dropped into a file in `src/test` to demonstrate that passing 400 accounts will result in a `recipientSize` of `400 - 256 = 144`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; +import { console } from "forge-std/console.sol"; +import { ImmutableSplitControllerFactory } from "src/controllers/ImmutableSplitControllerFactory.sol"; +import { ImmutableSplitController } from "src/controllers/ImmutableSplitController.sol"; + +interface ISplitsMain { + function createSplit(address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller) external returns (address); +} + +contract ZachTest is Test { + function testZach_RecipientSizeCappedAt256Accounts() public { + vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5"); + + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](400); + uint32[] memory bigPercentAllocations = new uint32[](400); + + for (uint i = 0; i < 400; i++) { + bigAccounts[i] = address(uint160(i)); + bigPercentAllocations[i] = 2500; + } + + // confirmation that 0xSplits will allow creating a split with this many accounts + // dummy acct passed as controller, but doesn't matter for these purposes + address split = ISplitsMain(0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE).createSplit(bigAccounts, bigPercentAllocations, 0, address(8888)); + + ImmutableSplitController controller = factory.createController(split, owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + + // added a public function to controller to read recipient size directly + uint savedRecipientSize = controller.ZachTest__recipientSize(); + assert(savedRecipientSize < 400); + console.log(savedRecipientSize); // 144 + } +} +``` + +**Recommendation** + +When packing the data in `_packSplitControllerData()`, check `recipientsSize` before downcasting to a uint8: + +```solidity +function _packSplitControllerData( + address owner, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) internal view returns (bytes memory data) { + uint256 recipientsSize = accounts.length; ++ if (recipientsSize > 256) revert InvalidSplit__TooManyAccounts(recipientSize); + ... +} +``` + +**Review** + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[M-03] In a mass slashing event, node operators are incentivized to get slashed[​](smart-contract-audit.md#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed) {#m-03-in-a-mass-slashing-event-node-operators-are-incentivized-to-get-slashed} +When the `OptimisticWithdrawalRecipient` receives funds from the beacon chain, it uses the following rule to determine the allocation: + +> If the amount of funds to be distributed is greater than or equal to 16 ether, it is assumed that it is a withdrawal (to be returned to the principal, with a cap on principal withdrawals of the total amount they deposited). + +> Otherwise, it is assumed that the funds are rewards. + +This value being as low as 16 ether protects against any predictable attack the node operator could perform. For example, due to the effect of hysteresis in updating effective balances, it does not seem to be possible for node operators to predictably bleed a withdrawal down to be below 16 ether (even if they timed a slashing perfectly). + +However, in the event of a mass slashing event, slashing punishments can be much more severe than they otherwise would be. To calculate the size of a slash, we: + +* take the total percentage of validator stake slashed in the 18 days preceding and following a user's slash +* multiply this percentage by 3 (capped at 100%) +* the full slashing penalty for a given validator equals 1/32 of their stake, plus the resulting percentage above applied to the remaining 31/32 of their stake + +In order for such penalties to bring the withdrawal balance below 16 ether (assuming a full 32 ether to start), we would need the percentage taken to be greater than `15 / 31 = 48.3%`, which implies that `48.3 / 3 = 16.1%` of validators would need to be slashed. + +Because the measurement is taken from the 18 days before and after the incident, node operators would have the opportunity to see a mass slashing event unfold, and later decide that they would like to be slashed along with it. + +In the event that they observed that greater than 16.1% of validators were slashed, Obol node operators would be able to get themselves slashed, be exited with a withdrawal of less than 16 ether, and claim that withdrawal as rewards, effectively stealing from the principal recipient. + +**Recommendations** + +Find a solution that provides a higher level of guarantee that the funds withdrawn are actually rewards, and not a withdrawal. + +**Review** + +Acknowledged. We believe this is a black swan event. It would require a major ETH client to be compromised, and would be a betrayal of trust, so likely not EV+ for doxxed operators. Users of this contract with unknown operators should be wary of such a risk. + +#### \[L-01] Obol fees will be applied retroactively to all non-distributed funds in the Splitter[​](smart-contract-audit.md#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter) {#l-01-obol-fees-will-be-applied-retroactively-to-all-non-distributed-funds-in-the-splitter} +When Obol decides to turn on fees, a call will be made to `ImmutableSplitController::updateSplit()`, which will take the predefined split parameters (the original user specified split with Obol's fees added in) and call `updateSplit()` to implement the change. + +```solidity +function updateSplit() external payable { + if (msg.sender != owner()) revert Unauthorized(); + + (address[] memory accounts, uint32[] memory percentAllocations) = getNewSplitConfiguration(); + + ISplitMain(splitMain()).updateSplit(split, accounts, percentAllocations, uint32(distributorFee())); +} +``` + +If we look at the code on `SplitsMain`, we can see that this `updateSplit()` function is applied retroactively to all funds that are already in the split, because it updates the parameters without performing a distribution first: + +```solidity +function updateSplit( + address split, + address[] calldata accounts, + uint32[] calldata percentAllocations, + uint32 distributorFee +) + external + override + onlySplitController(split) + validSplit(accounts, percentAllocations, distributorFee) +{ + _updateSplit(split, accounts, percentAllocations, distributorFee); +} +``` + +This means that any funds that have been sent to the split but have not yet be distributed will be subject to the Obol fee. Since these splitters will be accumulating all execution layer fees, it is possible that some of them may have received large MEV bribes, where this after-the-fact fee could be quite expensive. + +**Recommendation** + +The most strict solution would be for the `ImmutableSplitController` to store both the old split parameters and the new parameters. The old parameters could first be used to call `distributeETH()` on the split, and then `updateSplit()` could be called with the new parameters. + +If storing both sets of values seems too complex, the alternative would be to require that `split.balance <= 1` to update the split. Then the Obol team could simply store the old parameters off chain to call `distributeETH()` on each split to "unlock" it to update the fees. + +(Note that for the second solution, the ETH balance should be less than or equal to 1, not 0, because 0xSplits stores empty balances as `1` for gas savings.) + +**Review** + +Fixed as recommended in [PR 86](https://github.com/ObolNetwork/obol-manager-contracts/pull/86). + +#### \[L-02] If OWR is used with rebase tokens and there's a negative rebase, principal can be lost[​](smart-contract-audit.md#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost) {#l-02-if-owr-is-used-with-rebase-tokens-and-theres-a-negative-rebase-principal-can-be-lost} +The `OptimisticWithdrawalRecipient` is deployed with a specific token immutably set on the clone. It is presumed that that token will usually be ETH, but it can also be an ERC20 to account for future integrations with tokenized versions of ETH. + +In the event that one of these integrations used a rebasing version of ETH (like `stETH`), the architecture would need to be set up as follows: + +`OptimisticWithdrawalRecipient => rewards to something like LidoSplit.sol => Split Wallet` + +In this case, the OWR would need to be able to handle rebasing tokens. + +In the event that rebasing tokens are used, there is the risk that slashing or inactivity leads to a period with a negative rebase. In this case, the following chain of events could happen: + +* `distribute(PULL)` is called, setting `fundsPendingWithdrawal == balance` +* rebasing causes the balance to decrease slightly +* `distribute(PULL)` is called again, so when `fundsToBeDistributed = balance - fundsPendingWithdrawal` is calculated in an unchecked block, it ends up being near `type(uint256).max` +* since this is more than `16 ether`, the first `amountOfPrincipalStake - _claimedPrincipalFunds` will be allocated to the principal recipient, and the rest to the reward recipient +* we check that `endingDistributedFunds <= type(uint128).max`, but unfortunately this check misses the issue, because only `fundsToBeDistributed` underflows, not `endingDistributedFunds` +* `_claimedPrincipalFunds` is set to `amountOfPrincipalStake`, so all future claims will go to the reward recipient +* the `pullBalances` for both recipients will be set higher than the balance of the contract, and so will be unusable + +In this situation, the only way for the principal to get their funds back would be for the full `amountOfPrincipalStake` to hit the contract at once, and for them to call `withdraw()` before anyone called `distribute(PUSH)`. If anyone was to be able to call `distribute(PUSH)` before them, all principal would be sent to the reward recipient instead. + +**Recommendation** + +Similar to #74, I would recommend removing the ability for the `OptimisticWithdrawalRecipient` to accept non-ETH tokens. + +Otherwise, I would recommend two changes for redundant safety: + +1. Do not allow the OWR to be used with rebasing tokens. +2. Move the `_fundsToBeDistributed = _endingDistributedFunds - _startingDistributedFunds;` out of the unchecked block. The case where `_endingDistributedFunds` underflows is already handled by a later check, so this one change should be sufficient to prevent any risk of this issue. + +**Review** + +Fixed in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85) by removing the ability to use non-ETH tokens. + +#### \[L-03] LidoSplit can receive ETH, which will be locked in contract[​](smart-contract-audit.md#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract) {#l-03-lidosplit-can-receive-eth-which-will-be-locked-in-contract} +Each new `LidoSplit` is deployed as a clone, which comes with a `receive()` function for receiving ETH. + +However, the only function on `LidoSplit` is `distribute()`, which converts `stETH` to `wstETH` and transfers it to the `splitWallet`. + +While this contract should only be used for Lido to pay out rewards (which will come in `stETH`), it seems possible that users may accidentally use the same contract to receive other validator rewards (in ETH), or that Lido governance may introduce ETH payments in the future, which would cause the funds to be locked. + +**Proof of Concept** + +The following test can be dropped into `LidoSplit.t.sol` to confirm that the clones can currently receive ETH: + +```solidity +function testZach_CanReceiveEth() public { + uint before = address(lidoSplit).balance; + payable(address(lidoSplit)).transfer(1 ether); + assertEq(address(lidoSplit).balance, before + 1 ether); +} +``` + +**Recommendation** + +Introduce an additional function to `LidoSplit.sol` which wraps ETH into stETH before calling `distribute()`, in order to rescue any ETH accidentally sent to the contract. + +**Review** + +Fixed in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87/files) by adding a `rescueFunds()` function that can send ETH or any ERC20 (except `stETH` or `wstETH`) to the `splitWallet`. + +#### \[L-04] Upgrade to latest version of Solady to fix LibClone bug[​](smart-contract-audit.md#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug) {#l-04-upgrade-to-latest-version-of-solady-to-fix-libclone-bug} +In the recent [Solady audit](https://github.com/Vectorized/solady/blob/main/audits/cantina-solady-report.pdf), an issue was found the affects LibClone. + +In short, LibClone assumes that the length of the immutable arguments on the clone will fit in 2 bytes. If it's larger, it overlaps other op codes and can lead to strange behaviors, including causing the deployment to fail or causing the deployment to succeed with no resulting bytecode. + +Because the `ImmutableSplitControllerFactory` allows the user to input arrays of any length that will be encoded as immutable arguments on the Clone, we can manipulate the length to accomplish these goals. + +Fortunately, failed deployments or empty bytecode (which causes a revert when `init()` is called) are not problems in this case, as the transactions will fail, and it can only happen with unrealistically long arrays that would only be used by malicious users. + +However, it is difficult to be sure how else this risk might be exploited by using the overflow to jump to later op codes, and it is recommended to update to a newer version of Solady where the issue has been resolved. + +**Proof of Concept** + +If we comment out the `init()` call in the `createController()` call, we can see that the following test "successfully" deploys the controller, but the result is that there is no bytecode: + +```solidity +function testZach__CreateControllerSoladyBug() public { + ImmutableSplitControllerFactory factory = new ImmutableSplitControllerFactory(address(9999)); + bytes32 deploymentSalt = keccak256(abi.encodePacked(uint256(1102))); + address owner = address(this); + + address[] memory bigAccounts = new address[](28672); + uint32[] memory bigPercentAllocations = new uint32[](28672); + + for (uint i = 0; i < 28672; i++) { + bigAccounts[i] = address(uint160(i)); + if (i < 32) bigPercentAllocations[i] = 820; + else bigPercentAllocations[i] = 34; + } + + ImmutableSplitController controller = factory.createController(address(8888), owner, bigAccounts, bigPercentAllocations, 0, deploymentSalt); + assert(address(controller) != address(0)); + assert(address(controller).code.length == 0); +} +``` + +**Recommendation** + +Delete Solady and clone it from the most recent commit, or any commit after the fixes from [PR #548](https://github.com/Vectorized/solady/pull/548/files#diff-27a3ba4730de4b778ecba4697ab7dfb9b4f30f9e3666d1e5665b194fe6c9ae45) were merged. + +**Review** + +Solady has been updated to v.0.0.123 in [PR 88](https://github.com/ObolNetwork/obol-manager-contracts/pull/88). + +#### \[G-01] stETH and wstETH addresses can be saved on implementation to save gas[​](smart-contract-audit.md#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas) {#g-01-steth-and-wsteth-addresses-can-be-saved-on-implementation-to-save-gas} +The `LidoSplitFactory` contract holds two immutable values for the addresses of the `stETH` and `wstETH` tokens. + +When new clones are deployed, these values are encoded as immutable args. This adds the values to the contract code of the clone, so that each time a call is made, they are passed as calldata along to the implementation, which reads the values from the calldata for use. + +Since these values will be consistent across all clones on the same chain, it would be more gas efficient to store them in the implementation directly, which can be done with `immutable` storage values, set in the constructor. + +This would save 40 bytes of calldata on each call to the clone, which leads to a savings of approximately 640 gas on each call. + +**Recommendation** + +1. Add the following to `LidoSplit.sol`: + +```solidity +address immutable public stETH; +address immutable public wstETH; +``` + +2. Add a constructor to `LidoSplit.sol` which sets these immutable values. Solidity treats immutable values as constants and stores them directly in the contract bytecode, so they will be accessible from the clones. +3. Remove `stETH` and `wstETH` from `LidoSplitFactory.sol`, both as storage values, arguments to the constructor, and arguments to `clone()`. +4. Adjust the `distribute()` function in `LidoSplit.sol` to read the storage values for these two addresses, and remove the helper functions to read the clone's immutable arguments for these two values. + +**Review** + +Fixed as recommended in [PR 87](https://github.com/ObolNetwork/obol-manager-contracts/pull/87). + +#### \[G-02] OWR can be simplified and save gas by not tracking distributedFunds[​](smart-contract-audit.md#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds) {#g-02-owr-can-be-simplified-and-save-gas-by-not-tracking-distributedfunds} +Currently, the `OptimisticWithdrawalRecipient` contract tracks four variables: + +* distributedFunds: total amount of the token distributed via push or pull +* fundsPendingWithdrawal: total balance distributed via pull that haven't been claimed yet +* claimedPrincipalFunds: total amount of funds claimed by the principal recipient +* pullBalances: individual pull balances that haven't been claimed yet + +When `_distributeFunds()` is called, we perform the following math (simplified to only include relevant updates): + +```solidity +endingDistributedFunds = distributedFunds - fundsPendingWithdrawal + currentBalance; +fundsToBeDistributed = endingDistributedFunds - distributedFunds; +distributedFunds = endingDistributedFunds; +``` + +As we can see, `distributedFunds` is added to the `endingDistributedFunds` variable and then removed when calculating `fundsToBeDistributed`, having no impact on the resulting `fundsToBeDistributed` value. + +The `distributedFunds` variable is not read or used anywhere else on the contract. + +**Recommendation** + +We can simplify the math and save substantial gas (a storage write plus additional operations) by not tracking this value at all. + +This would allow us to calculate `fundsToBeDistributed` directly, as follows: + +```solidity +fundsToBeDistributed = currentBalance - fundsPendingWithdrawal; +``` + +**Review** + +Fixed as recommended in [PR 85](https://github.com/ObolNetwork/obol-manager-contracts/pull/85). + +#### \[I-01] Strong trust assumptions between validators and node operators[​](smart-contract-audit.md#i-01-strong-trust-assumptions-between-validators-and-node-operators) {#i-01-strong-trust-assumptions-between-validators-and-node-operators} +It is assumed that validators and node operators will always act in the best interest of the group, rather than in their selfish best interest. + +It is important to make clear to users that there are strong trust assumptions between the various parties involved in the DVT. + +Here are a select few examples of attacks that a malicious set of node operators could perform: + +1. Since there is currently no mechanism for withdrawals besides the consensus of the node operators, a minority of them sufficient to withhold consensus could blackmail the principal for a payment of up to 16 ether in order to allow them to withdraw. Otherwise, they could turn off their node operators and force the principal to bleed down to a final withdrawn balance of just over 16 ether. +2. Node operators are all able to propose blocks within the P2P network, which are then propogated out to the rest of the network. Node software is accustomed to signing for blocks built by block builders based on the metadata including quantity of fees and the address they'll be sent to. This is enforced by social consensus, with block builders not wanting to harm validators in order to have their blocks accepted in the future. However, node operators in a DVT are not concerned with the social consensus of the network, and could therefore build blocks that include large MEV payments to their personal address (instead of the DVT's 0xSplit), add fictious metadata to the block header, have their fellow node operators accept the block, and take the MEV for themselves. +3. While the withdrawal address is immutably set on the beacon chain to the OWR, the fee address is added by the nodes to each block. Any majority of node operators sufficient to reach consensus could create a new 0xSplit with only themselves on it, and use that for all execution layer fees. The principal (and other node operators) would not be able to stop them or withdraw their principal, and would be stuck with staked funds paying fees to the malicious node operators. + +Note that there are likely many other possible attacks that malicious node operators could perform. This report is intended to demonstrate some examples of the trust level that is needed between validators and node operators, and to emphasize the importance of making these assumptions clear to users. + +**Review** + +Acknowledged. We believe EIP 7002 will reduce this trust assumption as it would enable the validator exit via the execution layer withdrawal key. + +#### \[I-02] Provide node operator checklist to validate setup[​](smart-contract-audit.md#i-02-provide-node-operator-checklist-to-validate-setup) {#i-02-provide-node-operator-checklist-to-validate-setup} +There are a number of ways that the user setting up the DVT could plant backdoors to harm the other users involved in the DVT. + +Each of these risks is possible to check before signing off on the setup, but some are rather hidden, so it would be useful for the protocol to provide a list of checks that node operators should do before signing off on the setup parameters (or, even better, provide these checks for them through the front end). + +1. Confirm that `SplitsMain.getHash(split)` matches the hash of the parameters that the user is expecting to be used. +2. Confirm that the controller clone delegates to the correct implementation. If not, it could be pointed to delegate to `SplitMain` and then called to `transferControl()` to a user's own address, allowing them to update the split arbitrarily. +3. `OptimisticWithdrawalRecipient.getTranches()` should be called to check that `amountOfPrincipalStake` is equal to the amount that they will actually be providing. +4. The controller's `owner` and future split including Obol fees should be provided to the user. They should be able to check that `ImmutableSplitControllerFactory.predictSplitControllerAddress()`, with those parameters inputted, results in the controller that is actually listed on `SplitsMain.getController(split)`. + +**Review** + +Acknowledged. We do some of these already (will add the remainder) automatically in the launchpad UI during the cluster confirmation phase by the node operator. We will also add it in markdown to the repo. + +\\ diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/security/threat_model.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/security/threat_model.md new file mode 100644 index 0000000000..1e557a58a5 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/security/threat_model.md @@ -0,0 +1,155 @@ +--- +description: "Threat model for a Distributed Validator" +sidebar_label: "Charon Threat Model" +slug: /advanced-and-troubleshooting/security/threat_model +--- + +# Charon Threat Model + +This page outlines a threat model for Charon, in the context of it being a Distributed Validator middleware for Ethereum validator clients. + +## Actors + +* Node owner (NO) +* Cluster node operators (CNO) +* Rogue node operator (RNO) +* Outside attacker (OA) + +## General observations + +This page describes some considerations the Obol core team made about the security of a distributed validator in the context of its deployment and interaction with outside actors. + +The goal of this threat model is to provide transparency, but it is by no means a comprehensive audit or complete security reference. It’s a sharing of the experiences and thoughts we gained during the last few years building distributed validator technologies. + +While to the Beacon Chain, a distributed validator is seen in much the same way as a regular validator, and thus retains some of the same security considerations, Charon’s threat model is different from a validator client’s threat model because of its general design. + +While a validator client owns and operates on a set of validator private keys, the design of Charon allows its node operators to rarely (if ever) see the complete validator private keys, relying instead on modern cryptography to generate partial private key shares. + +An Ethereum distributed validator employs advanced signature primitives such that no operator ever handles the full validator private key in any standard lifecycle step: the [BLS digital signature scheme](https://en.wikipedia.org/wiki/BLS_digital_signature) employed by the Ethereum network allows distributed validators to individually sign a blob of data and then aggregate the resulting signatures in a transparent manner, never requiring any of the participating parties to know the full private key to do so. + +If the subset of the available Charon nodes is lower than a given threshold, the cluster is not able to continue with its duties. + +Given the collaborative nature of a Distributed Validator cluster, every operator must prioritise the liveness and well-being of the cluster. Charon, at the moment of writing this page cannot reward and penalise operators within a cluster independently. + +This implies that Charon’s threat model can’t quite be equated to that of a single validator client, since they work on a different - albeit similar - set of security concepts. + +## Identity private key + +A distributed validator cluster is made up of a number of nodes, often run by a number of independent operators. For each DV cluster there’s a set of Ethereum validator private keys on which they want to validate on behalf of. + +Alongside those, each node (henceforth ‘operator’) holds an SECP256K1 identity private key, referred to as an ENR, that identifies their node to the other cluster operators’ nodes. + +Exfiltration of said private key could lead to possible impersonation from an outside attacker, possibly leading to intra-cluster peering issues, eclipse attack risks, and degraded validator performance. + +Charon client communication is handled via BFT consensus, which is able to tolerate a given number of misbehaving nodes up to a certain threshold: once this threshold is reached, the cluster is not able to continue with its lifecycle and loses liveness guarantees (the validator goes offline). If more than two-thirds of nodes in a cluster are malicious, a cluster also loses safety guarantees (enough bad actors could collude to come to consensus on something slashable). + +Identity private key theft and the subsequent execution of a rogue cluster node is equivalent in the context of BFT consensus to a misbehaving node, hence the cluster can survive and continue with its duties up to what’s specified by the cluster’s BFT protocol’s parameters. + +The likelihood of this happening is low: an OA with enough knowledge of the topology of the operator’s network must steal `fault tolerance of the cluster + 1` identity private keys and run Charon nodes to subvert the distributed validator BFT consensus to push the validator offline. + +## Ethereum validator private key access + +A distributed validator cluster executes Ethereum validator duties by acting as a middleman between the beacon chain and a validator client. + +To do so, the cluster must have knowledge of the Ethereum validator’s private key. + +The design and implementation of Charon minimizes the chances of this by splitting the Ethereum validator private keys into parts, which are then assigned to each node operator. A [distributed key generation](https://en.wikipedia.org/wiki/Distributed_key_generation) (DKG) process is used in order to evenly and safely create the private key shares without any central party having access to the full private key. + +The cryptography primitives employed in Charon can allow a threshold of the node operator’s private key shares to be reconstructed into the whole validator private key if needed. + +While the facilities to do this are present in the form of CLI commands, as stated before Charon never reconstructs the key in normal operations since BLS digital signature system allows for signature aggregation. + +A distributed validator cluster can be started in two ways: + +1. An existing Ethereum validator private key is split by the private key holder, and distributed in a trusted manner among the operators. +2. The operators participate in a distributed key generation (DKG) process, to create private key shares that collectively can be used to sign validation duties as an Ethereum distributed validator. The full private key for the cluster never exists in one place during or after the DKG. + +In case 1, one of the node operators K has direct access to the Ethereum validator key and is tasked with the generation of other operator’s identity keys and key shards. + +It is clear that in this case the entirety of the sensitive material set is as secure as K’s environment; if K is compromised or malicious, the distributed validator could be slashed. + +Case 2 is different, because there’s no pre-existing Ethereum validator key in a single operator's hands: it will be generated using the FROST DKG algorithm. + +Assuming a successful DKG process, each operator will only ever handle its own key shares instead of the full Ethereum validator private key. + +A set of rogue operators composed of enough members to reconstruct the original Ethereum private keys might pose the risk of slashing for a distributed validator by colluding to produce slashable messages together. + +We deem this scenario’s likelihood as low, as it would mean that node operators decided to willfully slash the stake that they should be being rewarded for staking. + +Still, in the context of an outside attack, purposefully slashing a validator would mean stealing multiple operator key shares, which in turn means violating many cluster operator’s security almost at the same time. This scenario may occur if there is a 0-day vulnerability in a piece of software they all run or in case of node misconfiguration. + +## Rogue node operator + +Nodes are connected by means of either relay nodes, or directly to one another. + +Each node operator is at risk of being impeded by other nodes or by the relay operator in the execution of their duties. + +Nodes need to expose a set of TCP ports to be able to work, and the mere fact of doing that opens up the opportunity for rogue parties to execute DDoS attacks. + +Another attack surface for the cluster exists in rogue nodes purposefully filling the various inter-state databases with meaningless data, or more generally submitting bogus information to the other parties to slow down the processing or, in the case of a sybil attack, bring the cluster to a halt. + +The likelihood of this scenario is medium, because there’s no active threat hunting part: there’s no need for the rogue node operator to penetrate and compromise other nodes to disturb the cluster’s lifecycle. + +## Outside attackers interfering with a cluster + +There are two levels of sophistication in an OA: + +1. No knowledge of the topology of the cluster: The attacker doesn’t know where each cluster node is located and so can’t force fault tolerance +1 nodes offline if it can’t find them. +2. Knowledge of the topology of the network (or part of it) is possessed: the OA can operate DDoS attacks or try breaking into node’s servers - at that point, the “rogue node operator” scenario applies. + +The likelihood of this scenario is low: an OA needs extensive capabilities and sufficient incentive to be able to carry out an attack of this size. + +An outside attacker could also find and use vulnerabilities in the underlying cryptosystems and cryptography libraries used by Charon and other Ethereum clients. Forging signatures that fool Charon’s cryptographic library or other dependencies may be feasible, but forging signatures or otherwise finding a vulnerability in either the SECP256K1+ECDSA or BLS12-381+BLS cryptosystems we deem to be a low likelihood risk. + +## Malicious beacon nodes + +A malicious beacon node (BN) could prevent the distributed validator from operating its validation duties, and could plausibly increase the likelihood of slashing by serving Charon illegitimate information. + +If the amount of nodes configured with the malicious BN are equal to the byzantine threshold for the Charon BFT consensus protocol, the validation process can potentially halt since the BFT parameter threshold is reached - most of the nodes are byzantine - the system will reach consensus on a set of data that isn’t valid. + +We deem the likelihood of this scenario to be medium depending on the trust model associated with the BNs deployment (cloud, self-hosted, SaaS product): node operators should always host or at least trust their own beacon nodes. + +## Malicious Charon relays + +A Charon relay is used as a communication bridge between nodes that aren’t directly exposed on the Internet. It also acts as the peer discovery mechanism for a cluster. + +Once a peer’s IP address has been discovered via the relay, a direct connection can be attempted. Nodes can either communicate by exchanging data through a relay, or by using the relay as a means to establish a direct TCP connection to one another. + +A malicious relay owned by a OA could lead to: + +* Network topology discovery, facilitating the “outside attackers interactions with a cluster” scenario +* Impeding node communication, potentially impacting the BFT consensus protocol liveness (not security) and distributed validator duties +* DKG process disruption leading to frustration and potential abandonment by node operators: could lead to the usage of a standard Ethereum validator setup, which implies weaker security overall + +We note that BFT consensus liveness disruption can only happen if the number of nodes using the malicious relay for communication is equal to the byzantine nodes amount defined in the consensus parameters. + +This risk can be mitigated by configuring nodes with multiple relay URLs from only [trusted entities](../advanced/self-relay.md). + +The likelihood of this scenario is medium: Charon nodes are configured with a default set of relay nodes, so if an OA were to compromise those, it would lead to many cluster topologies getting discovered and potentially attacked and disrupted. + +## Compromised runtime files + +Charon operates with two runtime files: + +* A lock file used to address operator’s nodes, define the Ethereum validator public keys and the public key shares associated with it +* A cluster definition file used to define the operator’s addresses and identities during the DKG process + +The lock file is signed and validated by all the nodes participating in the cluster: assuming good security practices on the node operator side, and no bugs in Charon or its dependencies’ implementations, this scenario is unlikely. + +If one or more node operators are using less than ideal security practices an OA could rewire the Charon CLI flags to include the `--no-verify` flags, which disables lock file signature and hash verification (usually intended only for development purposes). + +By doing that, the OA can edit the lock file as it sees fit, leading to the “rogue node operator” scenario. An OA or RNO might also manage to social engineer their way into convincing other operators into running their malicious lock file with verification disabled. + +The likelihood of this scenario is low: an OA would need to compromise every node operator through social engineering to both use a different set of files, and to run its cluster with `--no-verify`. + +## Conclusions + +Distributed Validator Technology (DVT) helps maintain a high-assurance environment for Ethereum validators by leveraging modern cryptography to ensure no single point of failure is easily found in the system. + +As with any computing system, security considerations are to be expected in order to keep the environment safe. + +From the point of view of an Ethereum validator entity, running their services with a DV client can help greatly with availability, minimizing slashing risks, and maximizing participation in the network. + +On the other hand, one must take into consideration the risks involved with dishonest cluster operators, as well as rogue third-party beacon nodes or relay providers. + +In the end, we believe the benefits of DVT greatly outweigh the potential threats described in this overview. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/README.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/README.md new file mode 100644 index 0000000000..8de85c67b1 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Troubleshooting" +slug: /advanced-and-troubleshooting/troubleshooting +--- + +# Troubleshooting + diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/client_configurations.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/client_configurations.md new file mode 100644 index 0000000000..7f9c6aba31 --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/client_configurations.md @@ -0,0 +1,87 @@ +--- +description: "A reference for extra configuration of Ethereum Clients when running in DVs." +sidebar_label: "Client Configuration" +slug: /advanced-and-troubleshooting/troubleshooting/client_configurations +--- + +# Client Configuration + +Many execution, consensus, and validator clients need custom flags or parameters to work best with Distributed Validators. These settings are often dispersed across a number of documentation pages or example repos. This page aims to be a reference for each client and the specific additions they may require. + +## Lighthouse + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Lodestar + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Nimbus + +### Consensus Client + +When running a Nimbus Consensus Client you must add the following flag **to `charon run`**: + +```shell +--feature-set-enable=json_requests +``` + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Prysm + +### Consensus Client + +Nothing specific for distributed validators is required. If you are configuring MEV-boost, consult the settings you need [here](../advanced/enable-mev.mdx#consensus-clients). + +### Validator Client + +Required flags: + +```shell +--distributed +``` + +## Teku + +### Consensus Client + +Required flags: + +```shell +--validators-graffiti-client-append-format=DISABLED +``` + +### Validator Client + +Required flags: + +```shell +--Xobol-dvt-integration-enabled +``` diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/dkg_failure.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/dkg_failure.md new file mode 100644 index 0000000000..b370ed2d7a --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/dkg_failure.md @@ -0,0 +1,87 @@ +--- +description: "Handling DKG failure" +sidebar_label: "Handling DKG Failure" +slug: /advanced-and-troubleshooting/troubleshooting/dkg_failure +--- + +# Handling DKG Failure + +While the DKG process has been tested and validated against many different configuration instances, it can still encounter issues which might result in failure. + +Our DKG is designed in a way that doesn't allow for inconsistent results: either it finishes correctly for every peer, or it fails. + +This is a **safety** feature: you don't want to deposit an Ethereum distributed validator that not every operator is able to participate in. + +The most common source of issues lies in the network stack: if any of the peers' Internet connection glitches substantially, the DKG will fail. If you are attempting to run the `dkg` command in two places at once, or you have a `charon run` command with the same `charon-enr-private-key` as you are trying to DKG with, these may also disrupt a key generation ceremony. + +Charon's DKG doesn't allow peer reconnection once the process is started, but it does allow for re-connections before that. + +When you see the following message: + +```log +14:08:34.505 INFO dkg Waiting to connect to all peers... +``` + +this means your Charon instance is waiting for all the other cluster peers to start their DKG process: at this stage, peers can disconnect and reconnect at will, the DKG process will still continue. + +A log line will confirm the connection of a new peer: + +```log +14:08:34.523 INFO dkg Connected to peer 1 of 3 {"peer": "fantastic-adult"} +14:08:34.529 INFO dkg Connected to peer 2 of 3 {"peer": "crazy-bunch"} +14:08:34.673 INFO dkg Connected to peer 3 of 3 {"peer": "considerate-park"} +``` + +As soon as all the peers are connected, this message will be shown: + +```log +14:08:34.924 INFO dkg All peers connected, starting DKG ceremony +``` + +Past this stage **no disconnections are allowed**, and _all peers must leave their terminals open_ in order for the DKG process to complete: this is a synchronous phase, and every peer is required in order to reach completion. + +If for some reason the DKG process fails, you would see error logs that resemble this: + +```log +14:28:46.691 ERRO cmd Fatal error: sync step: p2p connection failed, please retry DKG: context canceled +``` + +As the error message suggests, the DKG process needs to be retried. + +## Cleaning up the `.charon` directory + +One cannot simply retry the DKG process: Charon refuses to overwrite any runtime file in order to avoid inconsistencies and private key loss. + +When attempting to re-run a DKG with an unclean data directory - which is either `.charon` or what was specified with the `--data-dir` CLI parameter - this is the error that will be shown: + +```log +14:44:13.448 ERRO cmd Fatal error: data directory not clean, cannot continue {"disallowed_entity": "cluster-lock.json", "data-dir": "/compose/node0"} +``` + +The `disallowed_entity` field lists all the files that Charon refuses to overwrite, while `data-dir` is the full path of the runtime directory the DKG process is using. + +In order to retry the DKG process one must delete the following entities, if present: + +* `validator_keys` directory +* `cluster-lock.json` file +* `deposit-data.json` file + +:::warning +The `charon-enr-private-key` file **must be preserved**, failure to do so requires the DKG process to be restarted from the beginning by creating a new cluster definition. +::: + +If you're doing a DKG with a custom cluster definition - for example, create with `charon create dkg`, rather than the Obol Launchpad - you can re-use the same file. + +Once this process has been completed, the cluster operators can retry a DKG. + +## Further debugging + +If you are trying to create an extremely large, geographically diverse cluster, there is a chance the process could be timing out. Consider adding the flags `--timeout=5m --shutdown-delay=60s` to allow more time for the ceremony to complete and safely shut down across all nodes. + +If for some reason the DKG process still fails, node operators are advised to reach out to the Obol team by opening an [issue](https://github.com/ObolNetwork/charon/issues), detailing the troubleshooting steps that were taken and providing **debug logs**. + +To enable debug logs, first clean up the Charon data directory as explained in [the previous section](dkg_failure.md#cleaning-up-the-charon-directory), then run your DKG command while appending `--log-level=debug` at the end. + +In order for the Obol team to debug your issue as quickly and precisely as possible, please provide full logs in text form, not through screenshots or display photos. + +Providing complete debug logs from all peers is particularly important, since it allows the team to reconstruct precisely what happened throughout the ceremony. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/errors.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/errors.md new file mode 100644 index 0000000000..6a51d3866a --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/errors.md @@ -0,0 +1,225 @@ +--- +description: "Errors & Resolutions" +sidebar_label: "Errors & Resolutions" +slug: /advanced-and-troubleshooting/troubleshooting/errors +--- + +# Errors & Resolutions + +All operators should try to restart their nodes and should check if they are on the latest stable version before attempting any other configuration change. You can restart and update with the following commands: + +```shell +docker compose down +git pull +docker compose up +``` + +You can check your logs using + +```shell +docker compose logs +``` + +## ENRs & Keys + +### How do I get my ENR if I want to generate it again? + +`cd` to the directory where your private keys are located (ex: `cd /path/to/charon/enr/private/key`) + +Run `docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 enr`. This prints the ENR on your screen. + +### What do I do if lose my `charon-enr-private-key`? + +If an ENR is lost, a new cluster operator can be created replacing the operator with the lost ENR. The steps to recover from a lost key are: + +1. Generate a new ENR with `charon create enr` +2. Complete the [replace-operator ceremony](../../run-a-dv/editing/replace-operator.md) within the cluster, using the new ENR public key as the `new-operator` and the lost ENR as the `old-operator`. Consult the `cluster-lock.json` file if you don't know the lost ENR public key. +3. Shut down the existing cluster across all operators. Wait at least two epochs fully offline to minimize any slashing risk. Have all operators replace their previous cluster artifacts with the new artifacts created in the replacement ceremony. +4. Bring the cluster nodes back online with the new artifacts. The lost ENR has now been cycled out of the cluster. + +To avoid having to disrupt cluster operation, it's recommended to make a secure backup of your ENR. + +### I can't find the keys anywhere + +The `charon-enr-private-key` is generated inside a hidden folder `.charon`. To view it, run `ls -al` in your terminal. This step may be a bit different for Windows. Else, if you are on macOS, press `Cmd + Shift + .` to view the `.charon` folder in the Finder application. + +## Lighthouse + +### Lighthouse says "downloading historical blocks" + +This means that Lighthouse is still syncing which will throw a lot of errors down the line. Wait for the sync before moving further. + +### Lighthouse gives the error `failed to request attester duties` + +This indicates there is something wrong with your Lighthouse beacon node. This might be because the request buffer is full as your node is never starting consensus since it never gets the duties. + +### Lighthouse gives the error `not enough time for a discovery search` + +This could be linked to a internet connection being too slow or relying on a slow third-party service such as Infura. + +## Beacon Node + +### `Error communicating with Beacon Node API` & `Error while connecting to beacon node event stream` + +This is likely due to Lighthouse not done syncing, wait and try again once synced. Can also be linked to Teku keystore issue. + +### Clock sync issues + +Either your clock server time is off, or you are talking to a remote beacon client that is super slow (this is why we advise against using services like Infura). + +### My beacon node API is flaky with lots of errors and timeouts + +A good quality beacon node API is critical to validator performance. It is always advised to run your own beacon node to ensure low latencies to boost validator performance. Using 3rd-party services like Infura's beacon node API has significant disadvantages since the quality is often low. Requests often return 500s or timeout. This results in lots of warnings and errors and failed duties. Running a local beacon node is always preferred. + +## Charon Errors + +### `Can't connect to Beacon API` + +If you are running EL and CL outside Obol on the same machine, you might need to open ports in your firewall to allow connections incoming from the docker instance. In order to know the IP of the docker network, run: `docker network inspect ` + +### `Attester failed in consensus component` + +The required number of operators defined in your cluster-lock file is probably not online to sign successfully. Make sure all operators are running the latest version of Charon. To check if some peers are not online: `docker logs charon-distributed-validator-node-charon-1 2>&1 | grep 'absent'` + +### `Load private key` + +Make sure you have successfully run a DKG before running the node. The key should be created and placed in the right directory during the ceremony. Also, make sure you are working in the right directory: `charon-distributed-validator-node`. + +### `Failed to confirm node connection` + +Wait for Teku & Lighthouse sync to be complete. + +### `Reserve relay circuit: reservation failed` + +`RESERVATION_REFUSED` is returned by the libp2p relay when some maximum limit has been reached. This is most often due to "maximum reservations per IP/peer". This is when your Charon node is restarting or in some error loop and constantly attempting to create new relay reservations reaching the maximum. + +To fix this error, stop your Charon node for 30mins before restarting it. This should allow the relay enough time to reset your IP/peer limits and should then allow new reservations. This could also be due to the relay being overloaded in general, so reaching a server wide "maximum connections" limit. This is an issue with relay scalability and we are working in a long term fix for this. + +### `Error opening relay circuit: NO_RESERVATION` + +Error opening relay circuit NO\_RESERVATION (204)\` indicates the peer isn't connected to the relay, so the the Charon client cannot connect to the peer via the relay. That might be because the peer is offline or the peer is configured to connect to a different relay. + +To fix this error, ensure the peer is online and configured with the exact same `--p2p-relays` flag. + +### `Couldnt fetch duty data from the beacon node` + +`msgFetcher` indicates a duty failed in the fetcher component when it failed to fetch the required data from the beacon node API. This indicates a problem with the upstream beacon node. + +### `Couldnt aggregate attestation due to failed attester duty` + +`msgFetcherAggregatorNoAttData` indicates an attestation aggregation duty failed in the fetcher component since it couldn't fetch the prerequisite attestation data. This indicates the associated attestation duty failed to obtain a cluster agreed upon value. + +### `Couldnt aggregate attestation due to insufficient partial v2 committee subscriptions` + +`msgFetcherAggregatorZeroPrepares` indicates an attestation aggregation duty failed in the fetcher component since it couldn't fetch the prerequisite aggregated v2 committee subscription. This indicates the associated prepare aggregation duty failed due to no partial v2 committee subscription submitted by the cluster validator clients. + +### `Couldnt aggregate attestation due to failed prepare aggregator duty` + +`msgFetcherAggregatorFailedPrepare` indicates an attestation aggregation duty failed in the fetcher component since it couldn't fetch the prerequisite aggregated v2 committee subscription. This indicates the associated prepare aggregation duty failed. + +### `Couldnt propose block due to insufficient partial randao signatures` + +`msgFetcherProposerFewRandaos` indicates a block proposer duty failed in the fetcher component since it couldn't fetch the prerequisite aggregated RANDAO. This indicates the associated randao duty failed due to insufficient partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to zero partial randao signatures` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed in the fetcher component since it couldn't fetch the prerequisite aggregated RANDAO. This indicates the associated randao duty failed due to no partial randao signatures submitted by the cluster validator clients. + +### `Couldnt propose block due to failed randao duty` + +`msgFetcherProposerZeroRandaos` indicates a block proposer duty failed in the fetcher component since it couldn't fetch the prerequisite aggregated RANDAO. This indicates the associated randao duty failed. + +### `Consensus algorithm didn't complete` + +`msgConsensus` indicates a duty failed in consensus component. This could indicate that insufficient honest peers participated in consensus or p2p network connection problems. + +### `Signed duty not submitted by local validator client` error + +`msgValidatorAPI` indicates that partial signature were never submitted by the local validator client. This could indicate that the local validator client is offline, or has connection problems with Charon, or has some other problem. See validator client logs for more details. + +### `Bug: partial signature database didn't trigger partial signature exchange` + +`msgParSigDBInternal` indicates a bug in the partial signature database as it is unexpected. + +### `No partial signatures received from peers` + +`msgParSigEx` indicates that no partial signature for the duty was received from any peer. This indicates all peers are offline or p2p network connection problems. + +### `Insufficient partial signatures received, minimum required threshold not reached` + +`msgParSigDBThreshold` indicates that insufficient partial signatures for the duty was received from peers. This indicates problems with peers or p2p network connection problems. + +### `Bug: threshold aggregation of partial signatures failed due to inconsistent signed data` + +`msgSigAgg` indicates that BLS threshold aggregation of sufficient partial signatures failed. This indicates inconsistent signed data. This indicates a bug in Charon as it is unexpected. + +### `Existing private key lock file found, another charon instance may be running on your machine` + +When you turn on the `--private-key-file-lock` option in Charon, it checks for a special file called the private key lock file. This file has the same name as the ENR private key file but with a `.lock` extension. If the private key lock file exists and is not older than 5 seconds, Charon won't run. It doesn't allow running multiple Charon instances with the same ENR private key. If the private key lock file has a timestamp older than 5 seconds, Charon will replace it and continue with its work. If you\`re sure that no other Charon instances are running, you can delete the private key lock file. + +### `Validator api 5xx response: mismatching validator client key share index, Mth key share submitted to Nth charon peer` + +The issue revolves around an invalid setup or deployment, where the validators private key shares don't match the ENR private key. There may have been a mix-up during deployment, leading to a mismatching validator client key share index. + +For example: Imagine node N is Alice, and node M is Bob, the error would read: `mismatching validator client key share index, Bob's key share submitted to Alice's charon node` Bob's private key share(s) are imported to a VC that is connected to Alice's Charon node. This is an invalid setup/deployment. Alice`s Charon node should only be connected to Alice`s VC. + +Check the partial public key shares of each node inside cluster-lock.json and see that matches with the public key inside `node(num)/validator_keys/keystore-0.json`. + +## Grafana + +### How to fix the Grafana dashboard? + +Sometimes, Grafana dashboard doesn't load any data the first time. You can solve this by following the steps below: + +* Click the Wheel Icon > Datasources. +* Click prometheus. +* Change the "Access" field from `Server (default)` to `Browser`. Press "Save & Test". It should fail. +* Change the "Access" field back to `Server (default)` and press "Save & Test". You should be presented with a green success icon saying "Data source is working" and you can return to the dashboard page. + +### `N/A` & `No data` in validator info panel + +Can be linked to a Teku keystore issue. + +## Prometheus + +### `Unauthorized: authentication error: invalid token` + +``` +You can ignore this error unless you have been contacted by the Obol Team +with monitoring credentials. In that case, follow [Monitoring your Node](../../run-a-dv/running/monitoring.md) in our guides. It does not affect cluster performance or prevent the cluster from running. +``` + +## Docker + +### How to fix `permission denied` errors? + +Permission denied errors can come up in a variety of manners, particularly on Linux and WSL for Windows systems. In the interest of security, the charon docker image runs as a non-root user, and this user often does not have the permissions to write in the directory you have checked out the code to. This can be generally be fixed with some of the following: + +* Running docker commands with `sudo`, if you haven't [set up docker to be run as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/) +* Changing the permissions of the `.charon` folder with the commands: + * `mkdir .charon` (if it doesn't already exist); + * `sudo chmod -R 666 .charon`. + +### I see a lot of errors after running `docker compose up` + +This is because both EL and CL clients start syncing, causing connectivity issues among the containers. Simply let the containers run for a while. You won't observe frequent errors when the EL client finishes syncing. You can also add a second beacon node endpoint for something like Infura by adding a comma separated API URL to the end of `CHARON_BEACON_NODE_ENDPOINTS` in the docker-compose.yml. + +### How do I fix the `plugin "loki" not found` error? + +If you get the following error when calling `docker compose up`: + +`Error response from daemon: error looking up logging plugin loki: plugin "loki" not found`. + +Then it probably means that the Loki docker driver isn't installed. In that case, run the following command to install loki: + +`docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions`. + +## Relay + +### `Resolve IP of p2p external host flag: lookup replace.with.public.ip.or.hostname:no such host` + +Replace `replace.with.public.ip.or.hostname` in the relay/docker-compose.yml with your real public IP or DNS hostname. + +### `Timeout resolving bootnode ENR: context deadline exceeded` + +The relay you are trying to connect to your peers via is offline or unreachable. diff --git a/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/test_command.md b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/test_command.md new file mode 100644 index 0000000000..83d3f55c5e --- /dev/null +++ b/versioned_docs/version-v1.9/advanced-and-troubleshooting/troubleshooting/test_command.md @@ -0,0 +1,162 @@ +--- +description: "Troubleshoot issues spotted by the test command" +sidebar_label: "Test Commands" +slug: /advanced-and-troubleshooting/troubleshooting/test_command +--- + +# Test Commands + +This page aims to give guidance on the causes, and potential for troubleshooting or improvement, of failed tests or low test scores from the [Charon Test commands](../../run-a-dv/prepare/test-a-cluster.mdx). + +## Peers + +### Charon Peers + +#### Ping + +* Peers might have not started their nodes or are not reachable. + +#### PingMeasure + +* Peer might be too far away (geographically) from you. +* If the connection to the peer is indirect, the route is from your node, to the relay, to the peer. Meaning you are measuring the travel time from you to the relay, and from the relay to the peer: (your node -> relay -> peer). This means, even if your peer's node is right next to yours, if the connection is being transmitted through a relay far away, the latency between your nodes might be too high to be effective. +* Your general network latency to the public internet might be high. Verify with the [`charon test infra`](../../run-a-dv/prepare/test-a-cluster.mdx#test-machine-and-network-performance) tests. +* If the connection to the peer is indirect, there is a potential that the relay might be overloaded or under-resourced, consider adding [alternative relays](../security/risks.md#risk-obol-hosting-the-relay-infrastructure), or preferably [opening charon's p2p port](../../learn/charon/charon-networking.md#libp2p-relays-and-peer-discovery) to the internet to establish direct peer to peer connections. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +#### DirectConn + +* Your or your peer's port might not be publicly exposed. +* Your or your peer's port might be behind a firewall. +* Your or your peer's port might be behind a strict NAT gateway. + +### Charon Relays + +#### PingRelay + +* Relay might be down or uncontactable for other reasons. + +#### PingMeasureRelay + +* Relay might be under heavy load. +* Your network latency might be high. Verify with the `charon test infra` tests. + +### Self + +#### Libp2pTCPPortOpenTest + +* There might be another process running on the designated port (tcp/3610 by default). +* The process might have died. + +## Beacon + +#### Ping + +* Beacon node might not be started or is not reachable. + +#### PingMeasure + +* Beacon node might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### Version + +* The beacon node version is not compatible with charon. + +#### IsSynced + +* Beacon node is not synced to the network. + +#### PeerCount + +* Beacon node does not have enough peers. This may result in slower fetching and broadcasting of slots and duties. + +#### PingLoad + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here. + +#### Simulation + +This is a load test, to enable it add the `--load-test` flag. + +Same causes as PingMeasure test apply here and additionally: + +* The infrastructure on which the beacon node runs (amount of RAM, disk IOPS) might not be enough to handle the number of simulated validators supplied in this test. + +## Validator + +#### Ping + +* Validator client might not be started or is not reachable. + +#### PingMeasure + +* Validator client might be too far away (geographically) from the charon client. Generally a low latency between a validator client and its charon client is important for timely signing. + +#### PingLoad + +Same causes as PingMeasure test apply here. + +## MEV + +#### Ping + +* MEV relay might not be started or is not reachable. + +#### PingMeasure + +* MEV relay might be too far away (geographically) from you. +* Your network latency might be high. Verify with the `charon test infra` tests. + +#### CreateBlock + +Same causes as PingMeasure test apply here and additionally: + +* MEV relay might be too slow in block production. + +#### CreateMultipleBlocks + +Same causes as CreateBlock test apply here. + +## Infra + +#### DiskWriteSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskWriteIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadSpeed + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### DiskReadIOPS + +* Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications). + +#### AvailableMemory + +* Your available memory (RAM) is not enough to run Charon. The minimum available memory should be 2GB, the recommended available memory is 4GB. Note that this test is a best estimate, as memory availability can be hard to predict, particularly if the command is run in a virtualised environment (i.e.: a Docker container). + +#### TotalMemory + +* Your total memory (RAM) may not be enough to run a full validating node. The recommended minimum total memory is 16GB. Specialised, or optimised deployments can use less RAM than the recommended minimum, but may require some monitoring to assert sufficient stability and performance. Read more in our [Deployment Best Practices](../../run-a-dv/prepare/deployment-best-practices.md#hardware-specifications) + +#### InternetLatency + +* Your internet latency to the nearest server is too high. Latency is expected to be at least less than 50ms and at best less than 20ms. + +#### InternetDownloadSpeed + +* Your internet download speed from the nearest test server is too low. Download speed is expected to be at least above 10Mb/s and at best above 50Mb/s. + +#### InternetUploadSpeed + +* Your internet upload speed to the nearest test server is too low. Upload speed is expected to be at least above 10Mb/s and at best above 50Mb/s. diff --git a/versioned_docs/version-v1.9/api/address.mdx b/versioned_docs/version-v1.9/api/address.mdx new file mode 100644 index 0000000000..a0ad46efdc --- /dev/null +++ b/versioned_docs/version-v1.9/api/address.mdx @@ -0,0 +1,18 @@ +--- +sidebar_label: "Address" +slug: /api/address +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Address + + + + + + + + + + diff --git a/versioned_docs/version-v1.9/api/cluster-definition.mdx b/versioned_docs/version-v1.9/api/cluster-definition.mdx new file mode 100644 index 0000000000..522e4f21b5 --- /dev/null +++ b/versioned_docs/version-v1.9/api/cluster-definition.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Cluster Definition" +slug: /api/cluster-definition +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Definition + + + + + + + + diff --git a/versioned_docs/version-v1.9/api/cluster-effectiveness.mdx b/versioned_docs/version-v1.9/api/cluster-effectiveness.mdx new file mode 100644 index 0000000000..7f36e47ffc --- /dev/null +++ b/versioned_docs/version-v1.9/api/cluster-effectiveness.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "Cluster Effectiveness" +slug: /api/cluster-effectiveness +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Effectiveness + + diff --git a/versioned_docs/version-v1.9/api/cluster-lock.mdx b/versioned_docs/version-v1.9/api/cluster-lock.mdx new file mode 100644 index 0000000000..d292f765d4 --- /dev/null +++ b/versioned_docs/version-v1.9/api/cluster-lock.mdx @@ -0,0 +1,38 @@ +--- +sidebar_label: "Cluster Lock" +slug: /api/cluster-lock +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Cluster Lock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.9/api/deposit-data.mdx b/versioned_docs/version-v1.9/api/deposit-data.mdx new file mode 100644 index 0000000000..744450549f --- /dev/null +++ b/versioned_docs/version-v1.9/api/deposit-data.mdx @@ -0,0 +1,17 @@ +--- +description: "Deposit Data related endpoints." +sidebar_label: "Deposit Data" +slug: /api/deposit-data +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Deposit Data + + + + + + + + diff --git a/versioned_docs/version-v1.9/api/dv-exit.mdx b/versioned_docs/version-v1.9/api/dv-exit.mdx new file mode 100644 index 0000000000..0661d8e03b --- /dev/null +++ b/versioned_docs/version-v1.9/api/dv-exit.mdx @@ -0,0 +1,24 @@ +--- +sidebar_label: "DV Exit" +slug: /api/dv-exit +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Exit + + + + + + + + + + + + + + + + diff --git a/versioned_docs/version-v1.9/api/dv-migrate.mdx b/versioned_docs/version-v1.9/api/dv-migrate.mdx new file mode 100644 index 0000000000..06883dff3e --- /dev/null +++ b/versioned_docs/version-v1.9/api/dv-migrate.mdx @@ -0,0 +1,11 @@ +--- +description: "DV Migrate related endpoints." +sidebar_label: "DV Migrate" +slug: /api/dv-migrate +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# DV Migrate + + diff --git a/versioned_docs/version-v1.9/api/metrics.mdx b/versioned_docs/version-v1.9/api/metrics.mdx new file mode 100644 index 0000000000..b60bfba08e --- /dev/null +++ b/versioned_docs/version-v1.9/api/metrics.mdx @@ -0,0 +1,11 @@ +--- +description: "MetricsController_metrics" +sidebar_label: "Metrics" +slug: /api/metrics +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Metrics + + diff --git a/versioned_docs/version-v1.9/api/owr-information.mdx b/versioned_docs/version-v1.9/api/owr-information.mdx new file mode 100644 index 0000000000..80354db6c5 --- /dev/null +++ b/versioned_docs/version-v1.9/api/owr-information.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "OWR Information" +slug: /api/owr-information +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# OWR Information + + diff --git a/versioned_docs/version-v1.9/api/state.mdx b/versioned_docs/version-v1.9/api/state.mdx new file mode 100644 index 0000000000..07c0e84eb7 --- /dev/null +++ b/versioned_docs/version-v1.9/api/state.mdx @@ -0,0 +1,10 @@ +--- +sidebar_label: "State" +slug: /api/state +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# State + + diff --git a/versioned_docs/version-v1.9/api/system.mdx b/versioned_docs/version-v1.9/api/system.mdx new file mode 100644 index 0000000000..5d413d9e55 --- /dev/null +++ b/versioned_docs/version-v1.9/api/system.mdx @@ -0,0 +1,13 @@ +--- +description: "System related endpoints." +sidebar_label: "System" +slug: /api/system +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# System + + + + diff --git a/versioned_docs/version-v1.9/api/techne-credentials.mdx b/versioned_docs/version-v1.9/api/techne-credentials.mdx new file mode 100644 index 0000000000..e8a795ca4c --- /dev/null +++ b/versioned_docs/version-v1.9/api/techne-credentials.mdx @@ -0,0 +1,16 @@ +--- +sidebar_label: "Techne Credentials" +slug: /api/techne-credentials +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Techne Credentials + + + + + + + + diff --git a/versioned_docs/version-v1.9/api/terms-and-conditions.mdx b/versioned_docs/version-v1.9/api/terms-and-conditions.mdx new file mode 100644 index 0000000000..26b13a5e91 --- /dev/null +++ b/versioned_docs/version-v1.9/api/terms-and-conditions.mdx @@ -0,0 +1,12 @@ +--- +sidebar_label: "Terms And Conditions" +slug: /api/terms-and-conditions +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Terms And Conditions + + + + diff --git a/versioned_docs/version-v1.9/api/test.mdx b/versioned_docs/version-v1.9/api/test.mdx new file mode 100644 index 0000000000..5bba732c58 --- /dev/null +++ b/versioned_docs/version-v1.9/api/test.mdx @@ -0,0 +1,13 @@ +--- +description: "Test related endpoints." +sidebar_label: "Test" +slug: /api/test +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# Test + + + + diff --git a/versioned_docs/version-v1.9/api/tvs.mdx b/versioned_docs/version-v1.9/api/tvs.mdx new file mode 100644 index 0000000000..224febfeea --- /dev/null +++ b/versioned_docs/version-v1.9/api/tvs.mdx @@ -0,0 +1,13 @@ +--- +description: "TVS (Total Value Staked) related endpoints." +sidebar_label: "TVS" +slug: /api/tvs +--- + +import ApiEndpoint from '@site/src/components/ApiEndpoint'; + +# TVS + + + + diff --git a/versioned_docs/version-v1.9/api/what-is-this-api.md b/versioned_docs/version-v1.9/api/what-is-this-api.md new file mode 100644 index 0000000000..6951dbffbb --- /dev/null +++ b/versioned_docs/version-v1.9/api/what-is-this-api.md @@ -0,0 +1,15 @@ +--- +description: "Download OpenAPI specifications: https://api.obol.tech/docs-json" +sidebar_label: "What is this API?" +slug: /api/what-is-this-api +--- + +# What is this API? + +### What is this API? + +This API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://launchpad.obol.org), a dApp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API can also be used via the [Obol-SDK](../sdk/index.md). + +Read more about Obol and how to use the [launchpad](https://launchpad.obol.org) on our [docs site](https://docs.obol.tech/). + +For enquiries: DV Labs: [support@dvlabs.tech](mailto:support@obol.tech) diff --git a/versioned_docs/version-v1.9/community-and-governance/community/README.md b/versioned_docs/version-v1.9/community-and-governance/community/README.md new file mode 100644 index 0000000000..30283c1bbe --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/community/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Community" +slug: /community-and-governance/community +--- + +# Community + diff --git a/versioned_docs/version-v1.9/community-and-governance/community/grants-program.md b/versioned_docs/version-v1.9/community-and-governance/community/grants-program.md new file mode 100644 index 0000000000..03f7ef65df --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/community/grants-program.md @@ -0,0 +1,36 @@ +--- +sidebar_label: "Grants Program" +slug: /community-and-governance/community/grants-program +--- + +# Grants Program + +## Program Status + +The Obol Grants Program is currently paused. + +Over its initial phase, the program supported a wide range of initiatives across the ecosystem and played a key role in accelerating growth, onboarding contributors, and strengthening the Collective. + +We’re incredibly proud of what was achieved and grateful to everyone who participated. + +→ [View Previously Funded Projects](https://x.com/Obol_Collective/status/2029557003371336159) + +## What’s Next + +Following this first phase, we’ve decided to take a step back and regroup. + +The goal is to: + +* Reflect on what worked well +* Identify areas for improvement +* Redesign the program to better align with the next phase of the Obol Collective + +We believe this pause will allow us to come back with a stronger, more focused, and more impactful grants program. + +## Stay Updated + +Updates on the future of the Grants Program will be shared as they become available. + +In the meantime, if you have ideas, feedback, or would like to stay involved: + +→ [Governance Forum](https://community.obol.org/) diff --git a/versioned_docs/version-v1.9/community-and-governance/community/staking-masters.md b/versioned_docs/version-v1.9/community-and-governance/community/staking-masters.md new file mode 100644 index 0000000000..906b6a9047 --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/community/staking-masters.md @@ -0,0 +1,27 @@ +--- +description: "Information about the Staking Mastery Program" +sidebar_label: "Staking Mastery Program (Archived)" +slug: /community-and-governance/community/staking-masters +--- + +# Staking Mastery Program (Archived) + +Information about the Staking Mastery Program can be found at https://squadstaking.com/mastery. + +## Achieving staking mastery + +The Staking Mastery program is a carefully curated cohort based program designed to empower and promote individuals who are passionate about advancing staking adoption through research, development and/or education.\\ + +![](/img/gitbook/image-54.png) + +In ancient Greece, masters were esteemed for their expertise and their role as mentors. A master would guide an apprentice through rigorous training and intellectual development. They often performed research, led workshops, or built entire guilds. This master-apprentice relationship was fundamental to the transmission of skills and knowledge in ancient Greek society. + +We're empowering the next generation of masters, the Ethereum Staking Masters. + +## How does it work? + +1. **Apply:** For those who are passionate about advancing Ethereum staking adoption through research, development and/or education. +2. **Interview:** Outstanding applicants will be interviewed to discuss their unique skills and how those can be best applied to advancing Ethereum staking adoption. +3. **Lead:** Selected Staking Masters will lead a project of their choosing for the length of their cohort, with support and recognition from DV Labs. + +Apply now at [squadstaking.com/mastery](https://squadstaking.com/mastery)! diff --git a/versioned_docs/version-v1.9/community-and-governance/community/techne.md b/versioned_docs/version-v1.9/community-and-governance/community/techne.md new file mode 100644 index 0000000000..f7897a2455 --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/community/techne.md @@ -0,0 +1,120 @@ +--- +description: "Information about the Techne Credential Program." +sidebar_label: "Techne" +slug: /community-and-governance/community/techne +--- + +# Techne + +Information about the Techne Credential Program can be found at https://squadstaking.com/techne. + +## Welcome to the Obol Network Techne Credential 👋 + +At Obol Network, we believe in empowering our community by providing them with the tools, knowledge, and recognition they deserve. The credential is designed to provide an on-chain attestation that identifies, acknowledges, and elevates individuals who demonstrate proven experience, knowledge, and commitment within the Distributed Validators domain. + +Drawing inspiration from the rich heritage of Ancient Greece, the name "Techne" reflects ideas of art, skill, or craft, representing technical mastery. Today, Techne embodies our vision to empower and uplift individuals who not only showcase technical expertise but also actively contribute to strengthening the staking ecosystem. + +## Why Earn the Credential? + +Each Obol Techne Credential is a verifiable, non-transferable NFT credential from Obol that proves your knowledge and experience operating Obol DVs. This on-chain attestation can then be used to showcase your experience, whether it’s to the Obol Core Team, other Obol community members, or the broader staking ecosystem. The credentials are defined in different tiers to ensure a progression path towards deeper expertise while offering an accessible entry point.\\ + +![](/img/gitbook/image-55.png) + +### Techne Credential Benefits + +The goal of the Obol Techne Credential is to give community validators more opportunities to become node operators. Today, many liquid staking protocols and other staking services are looking to build community-focused, permissionless, and more decentralized node operator sets. However, to be considered in those programs, validators must have proven experience and demonstrated ability to run high-performing nodes. The key benefit of the Obol Techne Credential is to give every validator to prove their knowledge and experience with Obol DVs. + +* **Recognition**: Receive a verifiable non-transferable NFT to prove and showcase your knowledge and experience running distributed validators. +* **Opportunities**: Credentialed individuals have proven experience running distributed validators, providing a path to access delegated stake in programs such as EtherFi’s Operation Solo Staker, Lido’s SimpleDVT Module and many more. + +## Program Overview + +### Eligibility + +The Obol Techne Credential is open to all community members interested in gaining knowledge and experience in running distributed validators. + +### Credentialing Journey + +The credentialing journey currently takes place in waves. Each wave lasts around 8 weeks and consists of a preparation period called the _Learning Phase_, followed by a hands-on experience period, called _Experience_, during which Obol monitors performance. Before the start of a wave, you already have the opportunity to create your squad. Credentials are awarded at the end of the wave based on a snapshot taken that verifies average performance during the Experience phase. + +Also, it's important to understand the concept of Credential Tiers. Currently, there are three: the Base Credential, the Bronze Credential and the Silver Credential. Base and Bronze are earned on testnet, with Silver earned on mainnet. + +### Learning Phase & Knowledge Assessment + +During each wave of our program, you will have the opportunity to join live training sessions on our Discord. We will teach the basics of Ethereum Proof of Stake and Obol Distributed Validators (DVs), and will demonstrate how to run your first DV. There will also be a training session where you can ask questions and receive answers directly from experienced community members. Head to Discord to see the full agenda of the current wave or next wave. + +Also, don’t forget to thoroughly read the [comprehensive documentation](https://docs.obol.tech/docs/int/Overview)! + +### Practical Experience + +To obtain your Obol Techne Credential, you will need to demonstrate your abilities to **set up, run, and maintain a DV cluster for multiple weeks**. For Base and Bronze, this is around 4 weeks. For Silver, this is around 8 weeks. This is the essence of the Techne credential, to allow you to showcase your experience in an honest and verifiable manner on-chain. + +### Performance Requirements + +You not only need to setup, run and maintain your DV, but also achieve **high performance.** Distributed Validators have been shown to outperform traditional validators, while providing much more [benefits and advantages](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/). + +The performance requirements are different depending on the different tiers. + +* For the **Base Credential**, you will need to run a DV cluster for 4 weeks with a performance near or above the [network average](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (open the link in incognito mode if the link does not work). We will take into account the overall performance of the cluster, not the individual performances of the operators. +* For the **Bronze Credential** , you will need to create and manage 50 validators for 4 weeks with a performance equal to or above the [average of the Liquid Staking Providers](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (index composed of Lido, RocketPool, Coinbase Cloud, StakeWise and EtherFi). We will also take into account the individual performance of the operators (the exact requirements will be announced soon). +* For the **Silver Credential,** you will need to create and manage 1 or more validators for 8 months on mainnet, with performance at near or above the network average. We will take into account the overall performance of the cluster as well as the individual performance of the operators. + +:::info +For Base + Bronze (testnet), if you require delegate hETH, we ask you to set the address 0x17E6F6270A101dc7687Cc9899889819EeAF8253f as the withdrawal recipient. We will not activate validators that have not done this. At the end of the wave, you will only be eligible for the Credentials after we receive the Holesky ETH back. +::: + +### Performance Monitoring + +To track and verify the performance of your DV, you and your squad mates are required to properly setup a monitoring credential. You can learn more about setting up your monitoring credential [here](../../run-a-dv/start/obol-monitoring.mdx). + +We are proud to share with you our [Techne Public Dashboard](https://grafana.monitoring.gcp.obol.tech/d/adgym07d8ak1sf/techne-credentials?orgId=6) (_open it in incognito mode if the link does not work_) which will allow you to track your performance and compare it to the requirements throughout your adventure. If the link does not work, open it in private browsing. + +Please note that **if you do not properly setup monitoring, you will not be eligible for any Credential**. + +### Claim your Credentials + +After a wave has ended and if you have _created_, _ran_, and successfully _exited_ your cluster, you will have the right to your new Techne Credential. + +We will make an announcement on our Discord and Twitter when the credentials are available to claim. + +Base and Bronze will require you to manually claim, while Silver will be automatically airdropped. + +## Get Started\* + +Start your journey without further delay. Please find here the various documents and information you will need to get started in the program: + +### [👉 Get Started Now](https://discord.com/invite/n6ebKsX46w) + +Additional Resources + +> [Quickstart Guide](https://docs.obol.tech/docs/start/quickstart_overview) +> +> [Support Channel on Discord](https://discord.obol.org) +> +> [Get Started Monitoring your Node](https://docs.obol.tech/docs/advanced/monitoring) + +## **Disclaimer** + +_Obol Network does not assume responsibility for any financial losses that may be incurred by individuals who choose to run on the Mainnet. Participants are advised to exercise due diligence and assess all risks associated with running on the Mainnet. Obol Network shall not be held liable for any damages, financial or otherwise, that may arise from participating in Mainnet operations._ + +## FAQ + +**It looks like there is no wave active right now, how can I earn a Techne Credential?** + +There are curerntly no active waves for earning Base or Bronze, but we plan to offer another wave in January of 2025. Currently, you still do have the ability to earn Silver. Please head to the [Obol Discord](https://discord.obol.org) to learn more about earning a Silver Techne Credential. + +**It has been 24 hours since I filled out the form to receive my Holesky ETH, but I haven't received anything yet. Is this normal?** + +This is probably due to an unusually high number of requests. Please wait for up to 48 hours and reach out to us on Discord. Also, please note that we do not distribute any Holseky ETH on weekends. + +**Can I qualify for the program if I run all the nodes on a single machine?** + +This is not aligned with the principle of distributed validators (DVs). You must form your cluster (squad) with other humans using other machines. + +**Can I take part in the program if I’m running on Mainnet?** + +Yes, those running a DV on mainnet have the opportunity to earn the Silver Techne Credential. + +**I don’t have the Base Credential but I have enough Holesky ETH to run 50 validators, can I aim for the Bronze Techne?** + +Yes, you can. Please send a message on [Discord](https://discord.obol.org) in the #techne-applicants channel explaining your desire to run for Bronze using your own Holesky ETH. diff --git a/versioned_docs/version-v1.9/community-and-governance/contribution/README.md b/versioned_docs/version-v1.9/community-and-governance/contribution/README.md new file mode 100644 index 0000000000..facdb224dc --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/contribution/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Contribution & Feedback" +slug: /community-and-governance/contribution +--- + +# Contribution & Feedback + diff --git a/versioned_docs/version-v1.9/community-and-governance/contribution/bug-report.md b/versioned_docs/version-v1.9/community-and-governance/contribution/bug-report.md new file mode 100644 index 0000000000..adda271288 --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/contribution/bug-report.md @@ -0,0 +1,61 @@ +--- +description: "Filing a bug report" +sidebar_label: "Filing a Bug Report" +slug: /community-and-governance/contribution/bug-report +--- + +# Filing a Bug Report + +Bug reports are critical to the rapid development of Obol. In order to make the process quick and efficient for all parties, it is best to follow some common reporting etiquette when filing to avoid double issues or miscommunications. + +## Checking if your issue exists + +Duplicate tickets are a hindrance to the development process and, as such, it is crucial to first check through Charon's existing issues to see if what you are experiencing has already been indexed. + +To do so, head over to the [issue page](https://github.com/ObolNetwork/charon/issues) and enter some related keywords into the search bar. This may include a sample from the output or specific components it affects. + +If searches have shown the issue in question has not been reported yet, feel free to open up a new issue ticket. + +## Writing quality bug reports + +A good bug report is structured to help the developers and contributors visualize the issue in the clearest way possible. It's important to be concise and use comprehensive language, while also providing all relevant information on-hand. Use short and accurate sentences without any unnecessary additions, and include all existing specifications with a list of steps to reproduce the expected problem. Issues that cannot be reproduced **cannot be solved**. + +If you are experiencing multiple issues, it is best to open each as a separate ticket. This allows them to be closed individually as they are resolved. + +An original bug report will very likely be preserved and used as a record and sounding board for users that have similar experiences in the future. Because of this, it is a great service to the community to ensure that reports meet these standards and follow the template closely. + +## The bug report template + +Below is the standard bug report template used by all of Obol's official repositories. + +```shell + + +## Expected Behavior + + +## Current Behavior + + +## Steps to Reproduce + +1. +2. +3. +4. +5. + +## Detailed Description + + +## Specifications + +Operating system: +Version(s) used: + +## Possible Solution + + +## Further Information + + + ## What is Charon? + + + + ## Charon explained + ``` + +**Bold text** + +Double asterisks `**` are used to define **boldface** text. Use bold text when the reader must interact with something displayed as text: buttons, hyperlinks, images with text in them, window names, and icons. + +```markdown +In the **Login** window, enter your email into the **Username** field and click **Sign in**. +``` + +**Italics** + +Underscores `_` are used to define _italic_ text. Style the names of things in italics, except input fields or buttons: + +```markdown +Here are some American things: + +- The _Spirit of St Louis_. +- The _White House_. +- The United States _Declaration of Independence_. + +``` + +Quotes or sections of quoted text are styled in italics and surrounded by double quotes `"`: + +```markdown +In the wise words of Winnie the Pooh _"People say nothing is impossible, but I do nothing every day."_ +``` + +**Code blocks** + +Tag code blocks with the syntax of the core they are presenting: + +````markdown + ```javascript + console.log(error); + ``` +```` + +**List items** + +All list items follow sentence structure. Only _names_ and _places_ are capitalized, along with the first letter of the list item. All other letters are lowercase: + +1. Never leave Nottingham without a sandwich. +2. Brian May played guitar for Queen. +3. Oranges. + +List items end with a period `.`, or a colon `:` if the list item has a sub-list: + +1. Charles Dickens novels: + 1. Oliver Twist. + 2. Nicholas Nickelby. + 3. David Copperfield. +2. J.R.R Tolkien non-fiction books: + 1. The Hobbit. + 2. Silmarillion. + 3. Letters from Father Christmas. + +**Unordered lists** + +Use the dash character `-` for un-numbered list items: + +```markdown +- An apple. +- Three oranges. +- As many lemons as you can carry. +- Half a lime. +``` + +**Special characters** + +Whenever possible, spell out the name of the special character, followed by an example of the character itself within a code block. + +```markdown +Use the dollar sign `$` to enter debug-mode. +``` + +**Keyboard shortcuts** + +When instructing the reader to use a keyboard shortcut, surround individual keys in code tags: + +```shell +Press `ctrl` + `c` to copy the highlighted text. +``` + +The plus symbol `+` stays outside of the code tags. + +#### Images + +The following rules and guidelines define how to use and store images. + +**Storage location** + +All images must be placed in the `/static/img` folder. For multiple images attributed to a single topic, a new folder within `/img/` may be needed. + +**File names** + +All file names are lower-case with dashes `-` between words, including image files: + +``` +concepts/ +├── content-addressed-data.md +├── images +│   └── proof-of-spacetime +│   └── post-diagram.png +└── proof-of-replication.md +└── proof-of-spacetime.md +``` + +_The framework and some information for this was forked from the original found on the_ [_Filecoin documentation portal_](https://docs.filecoin.io) diff --git a/versioned_docs/version-v1.9/community-and-governance/contribution/feedback.md b/versioned_docs/version-v1.9/community-and-governance/contribution/feedback.md new file mode 100644 index 0000000000..e779ba055c --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/contribution/feedback.md @@ -0,0 +1,12 @@ +--- +description: "Feedback for us" +sidebar_label: "Feedback" +slug: /community-and-governance/contribution/feedback +--- + +# Feedback + +If you have followed our quickstart guides, and whether you succeeded or failed at running the distributed validator successfully, we would like to hear your feedback on the process and where you encountered difficulties. + +* Please let us know by joining and posting on our [Discord](https://discord.gg/n6ebKsX46w). +* Also, feel free to add issues to our [GitHub repos](https://github.com/ObolNetwork). diff --git a/versioned_docs/version-v1.9/community-and-governance/governance.md b/versioned_docs/version-v1.9/community-and-governance/governance.md new file mode 100644 index 0000000000..21aa3c8b3c --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/governance.md @@ -0,0 +1,67 @@ +--- +sidebar_label: "Governance" +slug: /community-and-governance/governance +--- + +# Governance + +## Governance is in Transition + +Governance within Obol is currently paused and undergoing a transition phase. + +In its initial phase, Obol operated a delegate-based governance system, where OBOL token holders could delegate voting power and participate in proposal discussions, voting cycles, and funding decisions. This system enabled early coordination across our ecosystem, and the full history of proposals (OIPs), votes, and discussions remains publicly available on the [Governance Forum](https://community.obol.org/). In addition to discussions on the forum, you can explore past proposals, voting activity, and delegate participation through: + +* [Curia Dashboard](https://obol.curiahub.xyz/proposal) +* [Anticapture Dashboard](https://app.anticapture.com/obol) + +These tools provide a full view of previous governance cycles, including what was proposed, voted on, and how decisions were made. + +However, both internal learnings and broader ecosystem developments have made it clear that this model is not the right long-term solution for Obol. + +Several factors led us to pause governance and redesign it rather than continue with the current model. + +#### Structural Challenges in DAO Governance + +Structural challenges across DAO governance have become harder to ignore: low participation, recurring quorum risk, over-reliance on a small number of highly active delegates, and a growing gap between formal votes and actual execution. Even large DAOs have openly acknowledged these issues. More broadly, the retreat from token-vote governance at several major projects is a response to dysfunction, “governance theater,” and the need for more accountable execution models. + +#### Evolving Regulatory Landscape (SEC & CFTC Guidance while waiting for Clarity) + +While we’re waiting for the Clarity Act, the [joint SEC/CFTC guidance ](https://www.sec.gov/files/rules/interp/2026/33-11412.pdf)explicitly says the agencies are trying to draw clearer lines between securities and non-securities and that the new interpretation is meant to be a first step toward a clearer federal framework. It also emphasizes that crypto-asset analysis still turns on the economic realities of the arrangement and on the Howey test, including whether holders are led to expect profits from the essential managerial efforts of others. + +A crypto asset is less likely to be a security where it operates as part of a functional network, does not convey rights to income or enterprise value, and where any rewards arise from protocol-level participation rather than the managerial efforts of others. Governance features may exist, but are not determinative; the key question is whether the asset reflects participation in a network or an investment in a business. + +We also need to await the outcome of the passage of the Clarity Act through the US Senate and see what emerges from that process. + +#### Why This Means a Pause for Obol Governance + +For Obol, that means it would be premature to keep pretending the current model is the right long-term answer. Our existing design was delegate-based, portal-dependent, and ultimately still routed implementation through the Obol Association. That was a useful early-stage model, but it is not yet the governance system we want to scale with. Pausing now gives us room to design governance that is better suited to Obol specifically: more credible in practice, more tightly connected to real execution and stakeholder responsibility, and better aligned with the direction regulatory guidance is taking. The history of proposals, votes, and discussions remains live and publicly accessible, but the next phase needs to be more intentional than simply preserving the old rails. + +## Why Governance is Paused + +Rather than continuing with a system that is no longer fit for purpose, governance has been intentionally paused to allow space for redesign. + +Our goal is not to maintain governance for its own sake, but to build a model that: + +* Reflects the realities of how the Obol operates +* Enables effective decision-making and execution +* Aligns stakeholders with real participation and responsibility +* Is designed with long-term regulatory clarity in mind + +## What Comes Next + +We are actively exploring and designing the next iteration of governance for Obol. + +This includes rethinking: + +* The role of token holders +* The structure of decision-making +* The balance between execution and oversight +* How contributors and stakeholders meaningfully participate + +Progress is ongoing. While this work takes time, it is moving forward deliberately. + +## Stay Involved + +If you want to follow along or contribute to the future of Obol governance, we encourage you to join the discussion: + +→ [Governance Forum](https://community.obol.org/) diff --git a/versioned_docs/version-v1.9/community-and-governance/obol-token/README.md b/versioned_docs/version-v1.9/community-and-governance/obol-token/README.md new file mode 100644 index 0000000000..f2ff7e3af8 --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/obol-token/README.md @@ -0,0 +1,77 @@ +--- +sidebar_label: "The OBOL Token" +slug: /community-and-governance/obol-token +--- + +# The OBOL Token + +## Overview + +The OBOL token is the core coordination asset of the Obol Collective. It plays a central role in aligning participants, supporting the growth of the Distributed Validator ecosystem, and enabling long-term value creation across the network. + +Below you’ll find the key information related to the token, including contract details, distribution, and current status. + +## Token Information + +### Token Contract + +The official token contract address of the OBOL Token is[ 0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7) + +### Official Uniswap Pool + +The official Uniswap Pool for the OBOL Token is [https://app.uniswap.org/explore/pools/ethereum/0x29ecbccc2be2c0c9f87f4f84438bc9756a88f7cfe5ee91649a01240ae2242093](https://app.uniswap.org/explore/pools/ethereum/0x29ecbccc2be2c0c9f87f4f84438bc9756a88f7cfe5ee91649a01240ae2242093) + +## Current Token Utility + +Following recent updates and broader changes in the ecosystem, the OBOL token is evolving in how it is used. + +### Staking + +Staking is no longer actively promoted as a core token utility. + +* Existing staking contracts remain live and fully functional +* Users who have staked OBOL (via stOBOL) can keep their position as-is +* However, no new incentives or emissions are currently associated with staking + +This change reflects both: + +* A shift away from mechanisms that primarily extract value without strengthening the core network +* The need to ensure long-term alignment with evolving regulatory frameworks + +### Unstaking + +If you wish to unstake your tokens, you can do so at any time directly on-chain. + +This currently requires interacting with the staking contracts manually. + +We are working on a lightweight interface to simplify this process. + +Until then, you can follow the step-by-step guide [in the next page](guide-for-unstaking-obol.md). + +## Long-Term Token Vision + +The long-term role of OBOL remains unchanged. + +Our goal is for the token to become the economic backbone of the Distributed Validator ecosystem, tightly integrated into the core product and network dynamics. + +This includes: + +* Aligning incentives between operators, users, and contributors +* Supporting sustainable network growth +* Enabling deeper integration within validator workflows and infrastructure + +We are actively working toward a model where token utility is: + +* Product-driven rather than purely financial +* Tightly coupled to real usage and demand +* Sustainable over the long term + +## Ongoing Work + +Several initiatives are currently underway to strengthen OBOL’s role within the ecosystem: + +* [Strategic treasury operations to support long-term token health](https://x.com/Obol_Collective/status/2020904507895579028) +* [The Obol Economic Engine and Protocol Owned Liquidity](https://x.com/Obol_Collective/status/2019439135585628267) +* Deeper integration of the token within the Distributed Validator stack + +More details will be shared progressively as these efforts evolve. diff --git a/versioned_docs/version-v1.9/community-and-governance/obol-token/guide-for-unstaking-obol.md b/versioned_docs/version-v1.9/community-and-governance/obol-token/guide-for-unstaking-obol.md new file mode 100644 index 0000000000..edc66690ee --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/obol-token/guide-for-unstaking-obol.md @@ -0,0 +1,77 @@ +--- +sidebar_label: "Guide for Unstaking OBOL" +slug: /community-and-governance/obol-token/guide-for-unstaking-obol +--- + +# Guide for Unstaking OBOL + +With the [previous staking interface hosted by Tally being deprecated](https://x.com/tallyxyz/status/2033917127304814802?s=20), you can still unstake your OBOL at any time directly on-chain. All smart contracts remain live and fully functional. + +Below is a step-by-step guide to help you withdraw your tokens. + +## Overview + +If you previously staked OBOL, you received stOBOL in return. To unstake you will: + +* interact with the stOBOL contract +* call the unstake function +* receive your OBOL back in your wallet + +## Step-by-Step Guide + +### 1. Go to the stOBOL Contract + +Open the contract on Etherscan: + +[https://etherscan.io/address/0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC#writeContract](https://etherscan.io/address/0x6590cBBCCbE6B83eF3774Ef1904D86A7B02c2fCC#writeContract) + +### 2. Connect Your Wallet + +* Click “Connect to Web3” +* Select your wallet (e.g. MetaMask) +* Make sure you are on Ethereum Mainnet + +### 3. Find the unstake function + +In the list of functions, locate: + +``` +unstake +``` + +### 4. Enter the Amount + +You need to enter the amount in wei (18 decimals). + +Examples: + +* 1 OBOL → 1000000000000000000 +* 2 OBOL → 2000000000000000000 + +💡 Tip: If you want to fully exit, enter your full stOBOL balance. + +### 5. Submit the Transaction + +* Click “Write” +* Confirm the transaction in your wallet + +## What Happens Next + +Once the transaction is confirmed: + +* your stOBOL balance decreases +* your OBOL tokens are returned to your wallet + +You can verify the transaction on Etherscan. + +## Notes + +* You do not need to approve anything before unstaking +* You can unstake at any time, there are no lockups +* If you have multiple deposits, the contract handles this automatically + +## Coming Soon + +We are currently building a lightweight interface to make this process easier. + +Until then, you can always unstake using the steps above. diff --git a/versioned_docs/version-v1.9/community-and-governance/obol-token/token-distribution-and-liquidity.md b/versioned_docs/version-v1.9/community-and-governance/obol-token/token-distribution-and-liquidity.md new file mode 100644 index 0000000000..9f3269a9cc --- /dev/null +++ b/versioned_docs/version-v1.9/community-and-governance/obol-token/token-distribution-and-liquidity.md @@ -0,0 +1,42 @@ +--- +sidebar_label: "Token Distribution & Liquidity" +slug: /community-and-governance/obol-token/token-distribution-and-liquidity +--- + +# Token Distribution & Liquidity + +## Token Distribution + +The total supply is capped at 500 million tokens. The full supply is not immediately circulating and tokens will unlock over the coming months and years. + +![](/img/gitbook/12_Supply.png) + +### **Ecosystem Treasury & Retroactive Funding (RAF) | 38.8%** + +A significant portion of OBOL Tokens are allocated to the ecosystem treasury to drive innovation and decentralization. These funds support different initiatives, for example, [**SQUAD Goals**](https://community.obol.org/t/oip-3-obol-collective-2025-goals-proposal/)**, Grants & Incentives Funding** contributors who help to the growth of the protocol and the broader Collective and [**Retroactive Funding (RAF)**](https://blog.obol.org/raf1-results/)**,** rewarding contributions that have positively impacted the Obol Collective. Over time, the Obol Association plans to give additional control over these tokens to the community. + +### **Investors | 23.7%** + +Early investors played a key role in bringing the Obol Collective to life. This allocation ensures that individuals and entities that provided early financial support are fairly rewarded while adhering to best practices in responsible token vesting. + +### **Team | 19%** + +To attract and retain top-tier talent, a portion of tokens is reserved for core contributors, founders, and developers. This allocation aligns with the long-term vision of the project and is subject to a lock-up period similar to the one of investors. + +### **Community Incentives | 7.5%** + +To promote awareness and adoption, OBOL tokens will be used for user-focused initiatives that drive adoption of Obol DVs. The first of these initiative is the [Obol Incentives Program.](https://obol.org/incentives) + +### **Airdrop | 7.5%** + +As a community-first initiative, Obol has rewarded early contributors and supporters through a retroactive airdrop. This ensures ongoing participation in the Collective and strengthens the decentralized operator ecosystem. For more information about the Airdrop distribution, please [see this blog article](https://blog.obol.org/airdrop/). + +### **Public Sale via Coinlist | 3.6%** + +To ensure broad and fair token distribution, a portion of OBOL Tokens have been made available through a [Coinlist public sale](https://coinlist.co/obol) at better terms than investors. 50% of tokens purchased in the token sale will be fully unlocked and transferable at TGE, followed by a 12 month linear unlock for the remainder of the tokens. + +## Token Liquidity + +Once the token becomes transferable, the community will be able to track the distribution schedule and observe how the circulating supply increases over time according to the structured unlock plan. + +![](/img/gitbook/13_UnlockSchedule.png) diff --git a/versioned_docs/version-v1.9/learn/charon/README.md b/versioned_docs/version-v1.9/learn/charon/README.md new file mode 100644 index 0000000000..4afbb167ab --- /dev/null +++ b/versioned_docs/version-v1.9/learn/charon/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Charon" +slug: /learn/charon +--- + +# Charon + diff --git a/versioned_docs/version-v1.9/learn/charon/charon-cli-reference.md b/versioned_docs/version-v1.9/learn/charon/charon-cli-reference.md new file mode 100644 index 0000000000..753f19bc64 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/charon/charon-cli-reference.md @@ -0,0 +1,1153 @@ +--- +description: "A go-based middleware client for taking part in Distributed Validator clusters." +sidebar_label: "CLI Reference" +slug: /learn/charon/charon-cli-reference +--- + +# CLI Reference + +The following is a reference for Charon version [`v1.9.0`](https://github.com/ObolNetwork/charon/releases/tag/v1.9.0). Find the latest release on [our Github](https://github.com/ObolNetwork/charon/releases). + +The following are the top-level commands available to use. + +```markdown +charon --help +Charon enables the operation of Ethereum validators in a fault tolerant manner by splitting the validating keys across a group of trusted parties using threshold cryptography. + +Usage: + charon [command] + +Available Commands: + alpha Alpha subcommands provide early access to in-development features + combine Combine the private key shares of a distributed validator cluster into a set of standard validator private keys + completion Generate the autocompletion script for the specified shell + create Create artifacts for a distributed validator cluster + deposit Sign and fetch a new partial deposit. + dkg Participate in a Distributed Key Generation ceremony + enr Print the ENR that identifies this client + exit Exit a distributed validator. + help Help about any command + relay Start a libp2p relay server + run Run the charon middleware client + version Print version and exit + +Flags: + -h, --help Help for charon + +Use "charon [command] --help" for more information about a command. +``` + +## The `create` command + +The `create` command handles the creation of artifacts needed by Charon to operate. + +```markdown +charon create --help +Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases. + +Usage: + charon create [command] + +Available Commands: + cluster Create private keys and configuration files needed to run a distributed validator cluster locally + dkg Create the configuration for a new Distributed Key Generation ceremony using charon dkg + enr Create an Ethereum Node Record (ENR) private key to identify this charon client + +Flags: + -h, --help Help for create + +Use "charon create [command] --help" for more information about a command. +``` + +### Creating an ENR for Charon + +An `enr` is an Ethereum Node Record. It is used to identify this Charon client to its other counterparty Charon clients across the internet. + +```markdown +charon create enr --help +Create an Ethereum Node Record (ENR) private key to identify this charon client + +Usage: + charon create enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr +``` + +### Create a full cluster locally + +The `charon create cluster` command creates a set of distributed validators locally; including the private keys, a `cluster-lock.json` file, and deposit data. This command should only be used for solo-operation of distributed validators. To run a distributed validator cluster with a group of operators, it is preferable to create these artifacts using the [DV Launchpad](../intro/launchpad.md) and the `charon dkg` command. That way, no single operator custodies all of the private keys to a distributed validator. + +:::warning +This command produces new distributed validator private keys or handles and splits pre-existing traditional validator private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon create cluster --help +Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features. + +Usage: + charon create cluster [flags] + +Flags: + --cluster-dir string The target folder to create the cluster in. (default "./") + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --definition-file string Optional path to a cluster definition file or an HTTP URL. This overrides all other configuration flags. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for cluster + --insecure-keys Generates insecure keystore files. This should never be used. It is not supported on mainnet. + --keymanager-addresses strings Comma separated list of keymanager URLs to import validator key shares to. Note that multiple addresses are required, one for each node in the cluster, with node0's keyshares being imported to the first address, node1's keyshares to the second, and so on. + --keymanager-auth-tokens strings Authentication bearer tokens to interact with the keymanager URLs. Don't include the "Bearer" symbol, only include the api-token. + --name string The cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --nodes int The number of charon nodes in the cluster. Minimum is 3. + --num-validators int The number of distributed validators needed in the cluster. + --publish Publish lock file to obol-api. + --publish-address string The URL to publish the lock file to. (default "https://api.obol.tech/v1") + --split-existing-keys Split an existing validator's private key into a set of distributed validator private key shares. Does not re-create deposit data for this key. + --split-keys-dir string Directory containing keys to split. Expects keys in keystore-*.json and passwords in keystore-*.txt. Requires --split-existing-keys. + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. + --zipped Create a tar archive compressed with gzip of the cluster directory after creation. +``` + +### Creating the configuration for a DKG Ceremony + +This `charon create dkg` command creates a `cluster_definition.json` file used for the `charon dkg` command. + +```markdown +charon create dkg --help +Create a cluster definition file that will be used by all participants of a DKG. + +Usage: + charon create dkg [flags] + +Flags: + --compounding Enable compounding rewards for validators by using 0x02 withdrawal credentials. + --consensus-protocol string Preferred consensus protocol name for the cluster. Selected automatically when not specified. + --deposit-amounts ints List of partial deposit amounts (integers) in ETH. Values must sum up to at least 32ETH. + --dkg-algorithm string DKG algorithm to use; default, frost or pedersen. (default "default") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for dkg + --name string Optional cosmetic cluster name + --network string Ethereum network to create validators for. Options: mainnet, goerli, sepolia, hoodi, holesky, gnosis, chiado. (default "mainnet") + --num-validators int The number of distributed validators the cluster will manage (32ETH+ staked for each). (default 1) + --operator-addresses strings Comma-separated list of each operator's Ethereum address. + --operator-enrs strings Comma-separated list of each operator's Charon ENR address. + --output-dir string The folder to write the output cluster-definition.json file to. (default ".charon") + --publish Creates an invitation to the DKG ceremony on the DV Launchpad. Terms and conditions apply. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --target-gas-limit uint Preferred target gas limit for transactions. (default 60000000) + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + -t, --threshold int Optional override of threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +## The `dkg` command + +### Performing a DKG Ceremony + +The `charon dkg` command takes a `cluster_definition.json` file that instructs Charon on the terms of a new distributed validator cluster to be created. Charon establishes communication with the other nodes identified in the file, performs a distributed key generation ceremony to create the required threshold private keys, and signs deposit data for each new distributed validator. The command outputs the `cluster-lock.json` file and key shares for each Distributed Validator created. + +```markdown +charon dkg --help +Participate in a distributed key generation ceremony for a specific cluster definition that creates +distributed validator key shares and a final cluster lock configuration. Note that all other cluster operators should run +this command at the same time. + +Usage: + charon dkg [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --definition-file string The path to the cluster definition file or an HTTP URL. (default ".charon/cluster-definition.json") + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for dkg + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 1m0s) + --shutdown-delay duration Graceful shutdown delay. (default 5s) + --timeout duration Timeout for the DKG process, should be increased if DKG times out. (default 2m0s) + --zipped Create a tar archive compressed with gzip of the target directory after creation. +``` + +## The `run` command + +### Run the Charon middleware + +This `run` command accepts a `cluster-lock.json` file that was created either via a `charon create cluster` command or `charon dkg`. This lock file outlines the nodes in the cluster and the distributed validators they operate on behalf of. + +```markdown +charon run --help +Starts the long-running Charon middleware process to perform distributed validator duties. + +Usage: + charon run [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-submit-timeout duration Timeout for the submission-related HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --beacon-node-timeout duration Timeout for the HTTP requests Charon makes to the configured beacon nodes. (default 2s) + --builder-api Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network. + --consensus-protocol string Preferred consensus protocol name for the node. Selected automatically when not specified. + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + --feature-set string Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") + --feature-set-disable strings Comma-separated list of features to disable, overriding the default minimum feature set. + --feature-set-enable strings Comma-separated list of features to enable, overriding the default minimum feature set. + --graffiti strings Comma-separated list or single graffiti string to include in block proposals. List maps to validator's public key in cluster lock. Appends "OB" suffix to graffiti. Maximum 28 bytes per graffiti. + --graffiti-disable-client-append Disables appending "OB" suffix to graffiti. Increases maximum bytes per graffiti to 32. + -h, --help Help for run + --jaeger-address string [DISABLED] Listening address for jaeger tracing. + --jaeger-service string [DISABLED] Service name used for jaeger tracing. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --manifest-file string [DEPRECATED] The path to the cluster manifest file. If both cluster manifest and cluster lock files are provided, the cluster manifest file takes precedence. (default ".charon/cluster-manifest.pb") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). (default "127.0.0.1:3620") + --nickname string Human friendly peer nickname. Maximum 32 characters. + --no-verify Disables cluster definition and lock file verification. + --otlp-address string Listening address for OTLP gRPC tracing backend. + --otlp-headers strings Comma separated list of headers formatted as header=value, to include in OTLP requests. + --otlp-insecure Use insecure connection (no TLS) when connecting to OTLP endpoint. + --otlp-service-name string Service name used for OTLP gRPC tracing. (default "charon") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --private-key-file-lock Enables private key locking to prevent multiple instances using the same key. + --proc-directory string Directory to look into in order to detect other stack components running on the host. + --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-beacon-mock-fuzz Configures simnet beaconmock to return fuzzed responses. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) + --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") + --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. + --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version in hex of the custom test network. + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") + --vc-tls-cert-file string The path to the TLS certificate file used by charon for the validator client API endpoint. + --vc-tls-key-file string The path to the TLS private key file associated with the provided TLS certificate. +``` + +## The `exit` command + +A running Charon client will [aggregate and broadcast](../../run-a-dv/running/exit-a-dv.mdx) signed exit messages it receives from its validator client immediately. These `exit` commands are instead used to _pre-sign_ exit messages for an active distributed validator, to save to disk, or to broadcast; once enough of the operators of the cluster have submitted their partial exit signatures. Fully signed exit messages give a user or protocol a guarantee that they can exit an active validator at any point in future without the further assistance of the cluster's operators. In future, [execution-layer initiated exits](https://eips.ethereum.org/EIPS/eip-7002) will provide an even stronger guarantee that a validator can be exited by the withdrawal address it belongs to. + +```markdown +charon exit --help +Sign and broadcast distributed validator exit messages using a remote API. + +Usage: + charon exit [command] + +Available Commands: + active-validator-list List all active validators + broadcast Submit partial exit message for a distributed validator + delete Delete a signed exit message from the remote API + fetch Fetch a signed exit message from the remote API + sign Sign partial exit message for a distributed validator + +Flags: + -h, --help Help for exit + +Use "charon exit [command] --help" for more information about a command. +``` + +### Pre-sign exit messages for active validators + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. + +The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf). +::: + +This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index. + +```markdown +charon exit sign --help +Sign a partial exit message for a distributed validator and submit it to a remote API for aggregation. + +Usage: + charon exit sign [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for sign + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-index uint Validator index of the validator to exit, the associated public key must be present in the cluster lock manifest. If --validator-public-key is also provided, validator existence won't be checked on the beacon chain. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Delete exit message + +Delete a previously signed exit message for a given validator from the remote API. The required flag is either `--validator-public-key` of the validator message you wish to delete or `--all` to delete all validators' exit message. + +```markdown +charon exit delete --help +Deletes a partially signed exit message for a given validator from the remote API. + +Usage: + charon exit delete [flags] + +Flags: + --all Exit all currently active validators in the cluster. + -h, --help Help for delete + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Download fully signed exit messages for cold storage + +Once enough operators have submitted their partial signatures for an active validator, you can use the `charon exit fetch` command to download the complete exit message to a file for safe keeping. This file can be given to a delegator who wants a guarantee that they can exit the distributed validator if need be. + +```markdown +charon exit fetch --help +Fetches a fully signed exit message for a given validator from the remote API and writes it to disk. + +Usage: + charon exit fetch [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --fetched-exit-path string Path to store fetched signed exit messages. (default "./") + -h, --help Help for fetch + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### Broadcast a signed exit message + +The `charon exit broadcast` subcommand can be used to broadcast either a signed exit message from a file that was downloaded via the `fetch` command, or it can retrieve and broadcast an exit message directly from the API. + +```markdown +charon exit broadcast --help +Retrieves and broadcasts to the configured beacon node a fully signed validator exit message, aggregated with the available partial signatures retrieved from the publish-address. Can also read a signed exit message from disk, in order to be broadcasted to the configured beacon node. + +Usage: + charon exit broadcast [flags] + +Flags: + --all Exit all currently active validators in the cluster. + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --exit-epoch uint Exit epoch at which the validator will exit, must be the same across all the partial exits. (default 194048) + --exit-from-dir string Retrieves a signed exit messages from a pre-prepared files in a directory instead of --publish-address. + --exit-from-file string Retrieves a signed exit message from a pre-prepared file instead of --publish-address. + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for broadcast + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed exit to the publish-address API. (default 5m0s) + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-key string Public key of the validator to exit, must be present in the cluster lock manifest. If --validator-index is also provided, validator liveliness won't be checked on the beacon chain. +``` + +### List active validators + +The `charon exit active-validator-list` command returns a list of all distributed validators in the specified cluster whose status is ACTIVE\_ONGOING, meaning they can be exited. + +```markdown +charon exit active-validator-list --help +Returns a list of all the DV in the specified cluster whose status is ACTIVE_ONGOING, i.e. can be exited. + +Usage: + charon exit active-validator-list [flags] + +Flags: + --beacon-node-endpoints strings Comma separated list of one or more beacon node endpoint URLs. [REQUIRED] + --beacon-node-headers strings Comma separated list of headers formatted as header=value + --beacon-node-timeout duration Timeout for beacon node HTTP calls. (default 30s) + --fallback-beacon-node-endpoints strings A list of beacon nodes to use if the primary list are offline or unhealthy. + -h, --help Help for active-validator-list + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --plaintext Prints each active validator on a line, without any debugging or logging artifact. Useful for scripting. + --testnet-capella-hard-fork string Capella hard fork version of the custom test network. + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +## The `enr` command + +The standalone `charon enr` command prints an Ethereum Node Record (ENR) from the client's charon-enr-private-key. This serves as a public key that identifies this client to its peers. + +```markdown +charon enr --help +Prints an Ethereum Node Record (ENR) from this client's charon-enr-private-key. This serves as a public key that identifies this client to its peers. + +Usage: + charon enr [flags] + +Flags: + --data-dir string The directory where charon will store all its internal data. (default ".charon") + -h, --help Help for enr + --verbose Prints the expanded form of ENR. +``` + +## The `combine` command + +### Combine distributed validator key shares into a single validator key + +The `combine` command combines many validator key shares into a single Ethereum validator key. + +:::warning +This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret. +::: + +```markdown +charon combine --help +Combines the private key shares from a threshold of operators in a distributed validator cluster into a set of validator private keys that can be imported into a standard Ethereum validator client. + +Warning: running the resulting private keys in a validator alongside the original distributed validator cluster *will* result in slashing. + +Usage: + charon combine [flags] + +Flags: + --cluster-dir string Parent directory containing a number of .charon subdirectories from the required threshold of nodes in the cluster. (default "./") + --execution-client-rpc-endpoint string The address of the execution engine JSON-RPC API. + --force Overwrites private keys with the same name if present. + -h, --help Help for combine + --no-verify Disables cluster definition and lock file verification. + --output-dir string Directory to output the combined private keys to. (default "./validator_keys") + --testnet-chain-id uint Chain ID of the custom test network. + --testnet-fork-version string Genesis fork version of the custom test network (in hex). + --testnet-genesis-timestamp int Genesis timestamp of the custom test network. + --testnet-name string Name of the custom test network. +``` + +To run this command, one needs at least a threshold number of node operator's `.charon` directories, which need to be organized into a single folder: + +```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 +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── keystore-1.json + └── keystore-1.txt +``` + +That is, each operator `.charon` directory must be placed in a parent directory, and renamed to avoid conflicts. + +If for example the lock file defines 2 validators, each `validator_keys` directory must contain exactly 4 files, a JSON and TXT file for each validator. + +Those files must be named with an increasing index associated with the validator in the lock file, starting from 0. + +The chosen folder name does not matter, as long as it's different from `.charon`. + +At the end of the process `combine` will create a new directory specified by `--output-dir` containing the traditional validator private keystore. + +```shell +charon combine --cluster-dir="./cluster" --output-dir="./combined" +tree ./combined +combined +├── keystore-0.json +├── keystore-0.txt +├── keystore-1.json +└── keystore-1.txt +``` + +By default, the `combine` command will refuse to overwrite any private key that is already present in the destination directory. + +To force the process, use the `--force` flag. + +:::danger +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 for at least two epochs before starting a replacement validator or you are likely to be slashed.** +::: + +## The `deposit` command + +:::warning +Activating a validator with an incorrect withdrawal address likely results in a loss of the funds. Take care when preparing alternative deposit data for a single validator client. +::: + +For unused, inactive validators in an existing cluster, you can prepare alternative deposit data for them, allowing you to use them as validators for a different withdrawal address than originally intended. + +See the [advanced guide](../../advanced-and-troubleshooting/advanced/alter-withdrawal-addresses.md) for more. + +```markdown +charon deposit --help +Sign and fetch new deposit messages for unactivated validators using a remote API, enabling the modification of a withdrawal address after creation but before activation. + +Usage: + charon deposit [command] + +Available Commands: + fetch Fetch a full deposit message. + sign Sign a new partial deposit message. + +Flags: + -h, --help Help for deposit + +Use "charon deposit [command] --help" for more information about a command. +``` + +### Sign a deposit for an alternative withdrawal address + +A threshold of node operators must run `charon deposit sign` with matching parameters, to enable a new deposit data to be fetched with `charon deposit fetch`. + +```markdown +charon deposit sign --help +Signs new partial validator deposit messages using a remote API. + +Usage: + charon deposit sign [flags] + +Flags: + --deposit-amounts uints Comma separated list of partial deposit amounts (integers) in ETH. (default [32]) + -h, --help Help for sign + --lock-file string Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --private-key-file string Path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed deposit to the publish-address API. (default 5m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-keys strings [REQUIRED] List of validator public keys for which new deposits will be signed. + --withdrawal-addresses strings [REQUIRED] Withdrawal addresses for which the new deposits will be signed. Either a single address for all specified validator-public-keys or one address per key should be specified. +``` + +### Download a fully signed alternative deposit message + +`charon deposit fetch` outputs a file `.charon/deposit-data-.json` for use with the Ethereum deposit contract. + +```markdown +charon deposit fetch --help +Fetch full validator deposit messages using a remote API. + +Usage: + charon deposit fetch [flags] + +Flags: + --deposit-data-dir string Path to the directory in which fetched deposit data will be stored. (default ".charon/deposit-data-") + -h, --help Help for fetch + --lock-file string Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --private-key-file string Path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish-address string The URL of the remote API. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a signed deposit to the publish-address API. (default 5m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --validator-public-keys strings [REQUIRED] List of validator public keys for which new deposits will be signed. +``` + +## Host a relay + +Relays run a libp2p [circuit relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server that allows Charon clusters to perform peer discovery and for Charon clients behind strict NAT gateways to be communicated with. If you want to self-host a relay for your cluster(s) the following command will start one. + +```markdown +charon relay --help +Starts a libp2p circuit relay that charon clients can use to discover and connect to their peers. + +Usage: + charon relay [flags] + +Flags: + --auto-p2pkey Automatically create a p2pkey (secp256k1 private key used for p2p authentication and ENR) if none found in data directory. (default true) + --data-dir string The directory where charon will store all its internal data. (default ".charon") + --debug-address string Listening address (ip and port) for the pprof and QBFT debug API. It is not enabled by default. + -h, --help Help for relay + --http-address string Listening address (ip and port) for the relay http server serving runtime ENR. (default "127.0.0.1:3640") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --loki-addresses strings Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs. + --loki-service string Service label sent with logs to Loki. (default "charon") + --monitoring-address string Listening address (ip and port) for the monitoring API (prometheus). + --p2p-advertise-private-addresses Enable advertising of libp2p auto-detected private addresses. This doesn't affect manually provided p2p-external-ip/hostname. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-max-connections int Libp2p maximum number of peers that can connect to this relay. (default 16384) + --p2p-max-reservations int Updates max circuit reservations per peer (each valid for 30min) (default 512) + --p2p-relay-loglevel string Libp2p circuit relay log level. E.g., debug, info, warn, error. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://0.relay.obol.tech,https://1.relay.obol.tech,https://2.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. +``` + +You can also consider adding [alternative public relays](../../advanced-and-troubleshooting/security/risks.md) to your cluster by specifying a list of `p2p-relays` in [`charon run`](charon-cli-reference.md#run-the-charon-middleware). + +## Experimental commands + +These commands are subject to breaking changes until they are moved outside of the `alpha` subcommand in a future release. + +### Edit cluster configuration + +The `charon alpha edit` commands allow you to modify existing distributed validator cluster configurations. + +```markdown +charon alpha edit --help +Subcommands allow users to modify existing distributed validator cluster configurations, such as adding, removing or replacing operators. + +Usage: + charon alpha edit [command] + +Available Commands: + add-operators Add new operators to an existing distributed validator cluster + add-validators Add new validators to an existing distributed validator cluster + recreate-private-keys Create new private key shares to replace existing validator private key shares + remove-operators Remove operators from an existing distributed validator cluster + replace-operator Replace an operator in an existing distributed validator cluster + +Flags: + -h, --help Help for edit + +Use "charon alpha edit [command] --help" for more information about a command. +``` + +#### Add validators to a cluster + +The `charon alpha edit add-validators` command allows you to generate new validators and add them to an existing cluster. This process is very similar to the `charon dkg` ceremony, which requires all node operators to participate, because under the hood it runs the same DKG protocol with additional actions and verifications. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit add-validators --help +Generates and appends new validator keys to an existing distributed validator cluster. + +Usage: + charon alpha edit add-validators [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + --fee-recipient-addresses strings Comma separated list of Ethereum addresses of the fee recipient for each validator. Either provide a single fee recipient address or fee recipient addresses for each validator. + -h, --help Help for add-validators + --keymanager-address string The keymanager URL to import validator keyshares. + --keymanager-auth-token string Authentication bearer token to interact with keymanager API. Don't include the "Bearer" symbol, only include the api-token. + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --num-validators int The number of new validators to generate and add to the existing cluster. (default 1) + --output-dir string The destination folder for the new (combined) cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 1m0s) + --shutdown-delay duration Graceful shutdown delay. (default 5s) + --timeout duration Timeout for the command, should be increased if the command times out. (default 1m0s) + --unverified If charon has no access to the existing validator keys, this flag allows the addition to proceed, but skips hashing and signing the new cluster lock data. charon run must be started with --no-verify flag. + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") + --withdrawal-addresses strings Comma separated list of Ethereum addresses to receive the returned stake and accrued rewards for each validator. Either provide a single withdrawal address or withdrawal addresses for each validator. +``` + +#### Add operators to a cluster + +The `charon alpha edit add-operators` command adds new operators to an existing distributed validator cluster whilst keeping all validator public keys unchanged. All existing operators and new operators must participate in this ceremony. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit add-operators --help +Adds new operators to an existing distributed validator cluster, keeping validator public keys unchanged. + +Usage: + charon alpha edit add-operators [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for add-operators + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --new-operator-enrs strings Comma-separated list of the new operators to be added (Charon ENR addresses). + --no-verify Disables cluster definition and lock file verification. + --output-dir string The destination folder for the new cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 1m0s) + --shutdown-delay duration Graceful shutdown delay. (default 5s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +#### Remove operators from a cluster + +The `charon alpha edit remove-operators` command removes operators from an existing distributed validator cluster whilst leaving all validators intact. Remaining operators must participate in this ceremony. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit remove-operators --help +Removes operators from an existing distributed validator cluster, leaving all validators intact. + +Usage: + charon alpha edit remove-operators [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for remove-operators + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --new-threshold int Optional override of the new threshold required for signature reconstruction. Defaults to ceil(n*2/3) if zero. Warning, non-default values decrease security. All operators must use the same value. + --no-verify Disables cluster definition and lock file verification. + --operator-enrs-to-remove strings Comma-separated list of operators to be removed (Charon ENR addresses). + --output-dir string The destination folder for the new cluster data. Must be empty. Optional for removed operators. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --participating-operator-enrs strings Comma-separated list of operator ENRs participating in the ceremony. Required if --operator-enrs-to-remove specifies more operators to remove than the fault tolerance of the current cluster. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 1m0s) + --shutdown-delay duration Graceful shutdown delay. (default 5s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +#### Replace an operator in a cluster + +The `charon alpha edit replace-operator` command replaces an operator in an existing distributed validator cluster, keeping validator public keys unchanged. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit replace-operator --help +Replaces an operator in an existing distributed validator cluster, keeping validator public keys unchanged. + +Usage: + charon alpha edit replace-operator [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for replace-operator + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --new-operator-enr string The new operator to be added (Charon ENR address). + --no-verify Disables cluster definition and lock file verification. + --old-operator-enr string The old operator to be replaced (Charon ENR address). + --output-dir string The destination folder for the new cluster data. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 1m0s) + --shutdown-delay duration Graceful shutdown delay. (default 5s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +#### Recreate private key shares + +The `charon alpha edit recreate-private-keys` command creates new private key shares to replace the existing validator private keys whilst retaining the same operator identities and validator public keys. All operators must participate in this ceremony. + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +```markdown +charon alpha edit recreate-private-keys --help +Creates new private key shares to replace the existing validator private keys while retaining the same operator identities. + +Usage: + charon alpha edit recreate-private-keys [flags] + +Flags: + --execution-client-rpc-endpoint string Optional address of an execution engine JSON-RPC API. Used to validate smart contract signatures for Node Operators in the cluster. + -h, --help Help for recreate-private-keys + --lock-file string The path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json") + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --no-verify Disables cluster definition and lock file verification. + --output-dir string The destination folder for the new cluster artifacts. Must be empty. (default "distributed_validator") + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish the created cluster to a remote API. + --publish-address string The URL to publish the cluster to. (default "https://api.obol.tech/v1") + --publish-timeout duration Timeout for publishing a cluster, consider increasing if the cluster contains more than 200 validators. (default 1m0s) + --shutdown-delay duration Graceful shutdown delay. (default 5s) + --timeout duration Timeout for the protocol, should be increased if protocol times out. (default 1m0s) + --validator-keys-dir string Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys") +``` + +### Test your candidate distributed validator cluster + +Charon comes with a test suite for understanding the suitability and readiness of a given setup. + +```markdown +charon alpha test --help +Subcommands provide test suites to evaluate a cluster setup. The full validator stack can be tested - charon peers, consensus layer, validator client, MEV. Current machine's infra can be examined as well. + +Usage: + charon alpha test [command] + +Available Commands: + all Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. + beacon Run multiple tests towards beacon nodes + infra Run multiple hardware and internet connectivity tests + mev Run multiple tests towards MEV relays + peers Run multiple tests towards peer nodes + validator Run multiple tests towards validator client + +Flags: + -h, --help Help for test + +Use "charon alpha test [command] --help" for more information about a command. +``` + +#### Test all + +```markdown +charon alpha test all --help +Run tests towards peer nodes, beacon nodes, validator client, MEV relays, own hardware and internet connectivity. Verify that Charon can efficiently do its duties on the tested setup. + +Usage: + charon alpha test all [flags] + +Flags: + --beacon-endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + --beacon-load-test Enable load test, not advisable when testing towards external beacon nodes. + --beacon-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --beacon-simulation-custom int Run custom simulation with the specified amount of validators. + --beacon-simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --beacon-simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --beacon-simulation-verbose Show results for each request and each validator. + -h, --help Help for all + --infra-disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --infra-disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + --infra-internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --infra-internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --mev-beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --mev-endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + --mev-load-test Enable load test. + --mev-number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --mev-x-timeout-ms uint X-Timeout-Ms header flag for each request in milliseconds, used by MEVs to compute maximum delay for reply. (default 1000) + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --peers-definition-file string The path to the cluster definition file or an HTTP URL. + --peers-direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --peers-enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + --peers-keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --peers-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --peers-lock-file string The path to the cluster lock file defining the distributed validator cluster. + --peers-private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure PingLoad DirectConn Libp2pTCPPortOpen PingRelay PingMeasureRelay PeerCount PingLoad Simulate1 Simulate10 Simulate100 Simulate1000 Ping PingMeasure Synced Simulate500 SimulateCustom Version Ping PingMeasure PingLoad Ping PingMeasure CreateBlock InternetDownloadSpeed InternetUploadSpeed DiskWriteIOPS AvailableMemory DiskWriteSpeed DiskReadSpeed DiskReadIOPS TotalMemory InternetLatency] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --validator-validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` + +#### Test beacon node + +```markdown +charon alpha test beacon --help +Run multiple tests towards beacon nodes. Verify that Charon can efficiently interact with Beacon Node(s). + +Usage: + charon alpha test beacon [flags] + +Flags: + --endpoints strings [REQUIRED] Comma separated list of one or more beacon node endpoint URLs. + -h, --help Help for beacon + --load-test Enable load test, not advisable when testing towards external beacon nodes. + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --simulation-custom int Run custom simulation with the specified amount of validators. + --simulation-duration-in-slots int Time to keep running the simulation in slots. (default 32) + --simulation-file-dir string Time to keep running the simulation in slots. (default "./") + --simulation-verbose Show results for each request and each validator. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping Synced Simulate10 Simulate100 Simulate500 Simulate1000 PingMeasure Version PeerCount PingLoad Simulate1 SimulateCustom] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test infra + +```markdown +charon alpha test infra --help +Run multiple hardware and internet connectivity tests. Verify that Charon is running on host with sufficient capabilities. + +Usage: + charon alpha test infra [flags] + +Flags: + --disk-io-block-size-kb int The block size in kilobytes used for I/O units. Same value applies for both reads and writes. (default 4096) + --disk-io-test-file-dir string Directory at which disk performance will be measured. If none specified, current user's home directory will be used. + -h, --help Help for infra + --internet-test-servers-exclude strings List of server names to be excluded from the tests. To be specified only if you experience issues with a server that is wrongly considered best performing. + --internet-test-servers-only strings List of specific server names to be included for the internet tests, the best performing one is chosen. If not provided, closest and best performing servers are chosen automatically. + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [DiskReadSpeed TotalMemory InternetLatency InternetUploadSpeed DiskWriteSpeed DiskWriteIOPS DiskReadIOPS AvailableMemory InternetDownloadSpeed] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test MEV + +```markdown +charon alpha test mev --help +Run multiple tests towards MEV relays. Verify that Charon can efficiently interact with MEV relay(s). + +Usage: + charon alpha test mev [flags] + +Flags: + --beacon-node-endpoint string [REQUIRED] Beacon node endpoint URL used for block creation test. + --endpoints strings Comma separated list of one or more MEV relay endpoint URLs. + -h, --help Help for mev + --load-test Enable load test. + --number-of-payloads uint Increases the accuracy of the load test by asking for multiple payloads. Increases test duration. (default 1) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure CreateBlock] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --x-timeout-ms uint X-Timeout-Ms header flag for each request in milliseconds, used by MEVs to compute maximum delay for reply. (default 1000) +``` + +#### Test Charon peers + +```markdown +charon alpha test peers --help +Run multiple tests towards peer nodes. Verify that Charon can efficiently interact with Validator Client. + +Usage: + charon alpha test peers [flags] + +Flags: + --definition-file string The path to the cluster definition file or an HTTP URL. + --direct-connection-timeout duration Time to keep trying to establish direct connection to peer. (default 2m0s) + --enrs strings [REQUIRED] Comma-separated list of each peer ENR address. + -h, --help Help for peers + --keep-alive duration Time to keep TCP node alive after test completion, so connection is open for other peers to test on their end. (default 30m0s) + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 30s) + --lock-file string The path to the cluster lock file defining the distributed validator cluster. + --log-color string Log color; auto, force, disable. (default "auto") + --log-format string Log format; console, logfmt or json (default "console") + --log-level string Log level; debug, info, warn or error (default "info") + --log-output-path string Path in which to write on-disk logs. + --output-json string File path to which output can be written in JSON format. + --p2p-disable-reuseport Disables TCP port reuse for outgoing libp2p connections. + --p2p-external-hostname string The DNS hostname advertised by libp2p. This may be used to advertise an external DNS. + --p2p-external-ip string The IP address advertised by libp2p. This may be used to advertise an external IP. + --p2p-relays strings Comma-separated list of libp2p relay URLs or multiaddrs. (default [https://4.relay.obol.dev]) + --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --p2p-udp-address strings Comma-separated list of listening UDP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. + --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [PingMeasure PingLoad DirectConn Ping Libp2pTCPPortOpen] + --timeout duration Execution timeout for all tests. (default 1h0m0s) +``` + +#### Test validator client + +```markdown +charon alpha test validator --help +Run multiple tests towards validator client. Verify that Charon can efficiently interact with its validator client. + +Usage: + charon alpha test validator [flags] + +Flags: + -h, --help Help for validator + --load-test-duration duration Time to keep running the load tests in seconds. For each second a new continuous ping instance is spawned. (default 5s) + --output-json string File path to which output can be written in JSON format. + --publish Publish test result file to obol-api. + --publish-address string The URL to publish the test result file to. (default "https://api.obol.tech/v1") + --publish-private-key-file string The path to the charon enr private key file, used for signing the publish request. Temporary key will be generated if the file does not exist. (default ".charon/charon-enr-private-key") + --quiet Do not print test results to stdout. + --test-cases strings List of comma separated names of tests to be executed. Available tests are: [Ping PingMeasure PingLoad] + --timeout duration Execution timeout for all tests. (default 1h0m0s) + --validator-api-address string Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") +``` diff --git a/versioned_docs/version-v1.9/learn/charon/charon-networking.md b/versioned_docs/version-v1.9/learn/charon/charon-networking.md new file mode 100644 index 0000000000..1d9e45d0e9 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/charon/charon-networking.md @@ -0,0 +1,82 @@ +--- +sidebar_label: "Charon Networking" +slug: /learn/charon/charon-networking +--- + +# Charon Networking + +## Charon networking + +### Overview[​](charon-networking.md#overview) {#overview} +This document describes Charon's networking model which can be divided into two parts: the [_internal validator stack_](charon-networking.md#internal-validator-stack) and the [_external p2p network_](charon-networking.md#external-p2p-network). + +### Internal Validator Stack[​](charon-networking.md#internal-validator-stack) {#internal-validator-stack} +![](/img/gitbook/image-22.png) + +Charon is a middleware DVT client and is therefore connected to an upstream beacon node and a downstream validator client is connected to it. Each operator should run the whole validator stack (all 4 client software types), either on the same machine or on different machines. The networking between the nodes should be private and not exposed to the public internet. + +Related Charon configuration flags: + +* `--beacon-node-endpoints`: Connects Charon to one or more beacon nodes. +* `--validator-api-address`: Address for Charon to listen on and serve requests from the validator client. + +### External P2P Network[​](charon-networking.md#external-p2p-network) {#external-p2p-network} +![](/img/gitbook/image-23.png) + +The Charon clients in a DV cluster are connected to each other via a small p2p network consisting of only the clients in the cluster. Peer IP addresses are discovered via an external "relay" server. The p2p connections are over the public internet so the Charon p2p port must be publicly accessible. Charon leverages the popular [libp2p](https://libp2p.io/) protocol. + +Related [Charon configuration flags](charon-cli-reference.md): + +* `--p2p-tcp-address`: Address for Charon to listen on and serve p2p requests. +* `--p2p-relays`: Connect Charon to one or more relay servers. +* `--private-key-file`: Private key identifying the Charon client. + +#### LibP2P Authentication and Security[​](charon-networking.md#libp2p-authentication-and-security) {#libp2p-authentication-and-security} +Each Charon client has a secp256k1 private key. The associated public key is encoded into the [cluster lock file](cluster-configuration.md#cluster-lock-file) to identify the nodes in the cluster. For ease of use and to align with the Ethereum ecosystem, Charon encodes these public keys in the [ENR format](https://eips.ethereum.org/EIPS/eip-778), not in [libp2p's Peer ID format](https://docs.libp2p.io/concepts/fundamentals/peers/). + +:::warning +Each Charon node's secp256k1 private key is critical for authentication and must be kept secure to prevent cluster compromise. + +Do not use the same key across multiple clusters, as this can lead to security issues. + +For more on p2p security, refer to [libp2p's article](https://docs.libp2p.io/concepts/security/security-considerations). +::: + +Charon currently only supports libp2p tcp connections with [noise](https://noiseprotocol.org/) security and only accepts incoming libp2p connections from peers defined in the cluster lock. + +#### LibP2P Relays and Peer Discovery[​](charon-networking.md#libp2p-relays-and-peer-discovery) {#libp2p-relays-and-peer-discovery} +Relays are simple libp2p servers that are publicly accessible supporting the [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) protocol. Circuit-relay is a libp2p transport protocol that routes traffic between two peers over a third-party “relay” peer. + +Obol hosts a publicly accessible relay at [https://0.relay.obol.tech](https://0.relay.obol.tech/) and will work with other organisations in the community to host alternatives. Anyone can host their own relay server for their DV cluster. + +Each Charon node knows which peers are in the cluster from the ENRs in the cluster lock file, but their IP addresses are unknown. By connecting to the same relay, nodes establish “relay connections” to each other. Once connected via relay they exchange their known public addresses via libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol. The relay connection is then upgraded to a direct connection. If a node’s public IP changes, nodes once again connect via relay, exchange the new IP, and then connect directly once again. + +Note that in order for two peers to discover each other, they must connect to the same relay. Cluster operators should therefore coordinate which relays to use. + +Libp2p’s [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify) protocol attempts to automatically detect the public IP address of a Charon client without the need to explicitly configure it. If this however fails, the following two configuration flags can be used to explicitly set the publicly advertised address: + +* `--p2p-external-ip`: Explicitly sets the external IP address. +* `--p2p-external-hostname`: Explicitly sets the external DNS host name. + +:::warning +If a pair of Charon clients are not publicly accessible, due to being behind a NAT, they will not be able to upgrade their relay connections to a direct connection. Even though this is supported, it isn’t recommended as relay connections introduce additional latency and reduced throughput and will result in decreased validator effectiveness and possible missed block proposals and attestations. +::: + +Libp2p’s circuit-relay connections are end-to-end encrypted, even though relay servers accept connections between nodes from multiple different clusters, relays are merely routing opaque connections. And since Charon only accepts incoming connections from other peers in its cluster, the use of a relay doesn’t allow connections between clusters. + +Only the following three libp2p protocols are established between a Charon node and a relay itself: + +* [circuit-relay](https://docs.libp2p.io/concepts/nat/circuit-relay/): To establish relay e2e encrypted connections between two peers in a cluster. +* [identify](https://docs.libp2p.io/concepts/fundamentals/protocols/#identify): Auto-detection of public IP addresses to share with other peers in the cluster. +* [peerinfo](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfo.go): Exchanges basic application [metadata](https://github.com/ObolNetwork/charon/blob/main/app/peerinfo/peerinfopb/v1/peerinfo.proto) for improved operational metrics and observability.\\ + +All other Charon protocols are only established between nodes in the same cluster. + +#### Scalable Relay Clusters[​](charon-networking.md#scalable-relay-clusters) {#scalable-relay-clusters} +In order for a Charon client to connect to a relay, it needs the relay's [multiaddr](https://docs.libp2p.io/concepts/fundamentals/addressing/) (containing its public key and IP address). But a single multiaddr can only point to a single relay server which can easily be overloaded if too many clusters connect to it. Charon therefore supports resolving a relay’s multiaddr via HTTP GET request. Since Charon also includes the unique `cluster-hash` header in this request, the relay provider can use [consistent header-based load-balancing](https://cloud.google.com/load-balancing/docs/https/traffic-management-global#traffic_steering_header-based_routing) to map clusters to one of many relays using a single HTTP address. + +The relay supports serving its runtime public multiaddrs via its `--http-address` flag. + +E.g., [https://0.relay.obol.tech](https://0.relay.obol.tech/) is actually a load-balancer that routes HTTP requests to one of many relays based on the `cluster-hash` header returning the target relay’s multiaddr which the Charon client then uses to connect to that relay. + +The charon `--p2p-relays` flag therefore supports both multiaddrs as well as HTTP URLs. diff --git a/versioned_docs/version-v1.9/learn/charon/cluster-configuration.md b/versioned_docs/version-v1.9/learn/charon/cluster-configuration.md new file mode 100644 index 0000000000..35b677f482 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/charon/cluster-configuration.md @@ -0,0 +1,198 @@ +--- +description: "Documenting a Distributed Validator Cluster in a standardised file format" +sidebar_label: "Cluster Configuration" +slug: /learn/charon/cluster-configuration +--- + +# Cluster Configuration + +:::warning +These cluster definition and cluster lock files are a work in progress. The intention is for the files to be standardised for operating distributed validators via the [EIP process](https://eips.ethereum.org/) when appropriate. +::: + +This document describes the configuration options for running a Charon client or cluster. + +A Charon cluster is configured in two steps: + +* `cluster-definition.json` which defines the intended cluster configuration before keys have been created in a distributed key generation ceremony. +* `cluster-lock.json` which includes and extends `cluster-definition.json` with distributed validator BLS public key shares. + +In the case of a solo operator running a cluster, the [`charon create cluster`](charon-cli-reference.md#create-a-full-cluster-locally) command combines both steps into one and just outputs the final `cluster-lock.json` without a DKG step. + +## Cluster Definition File + +The `cluster-definition.json` is provided as input to the DKG which generates keys and the `cluster-lock.json` file. + +### Using the CLI + +The [`charon create dkg`](charon-cli-reference.md#creating-the-configuration-for-a-dkg-ceremony) command is used to create the `cluster-definition.json` file which is used as input to `charon dkg`. + +The schema of the `cluster-definition.json` is defined as: + +```json +{ + "name": "best cluster", // Optional cosmetic identifier + "uuid": "1234-abcdef-1234-abcdef", // Random unique identifier. + "creator": { + "address": "0x123..abfc", //ETH1 address of the creator + "config_signature": "0x123654...abcedf" // EIP712 Signature of config_hash using creator privkey + }, + "version": "v1.8.0", // Schema version + "num_validators": 1, // Number of distributed validators to be created in cluster-lock.json + "threshold": 3, // Optional threshold required for signature reconstruction + "dkg_algorithm": "default", // Optional DKG algorithm for key generation + "fork_version": "0x01017000", // Chain/Network identifier + "config_hash": "0xabcfde...acbfed", // Hash of the static (non-changing) fields + "timestamp": "2025-01-01T12:00:00+00:00", // Creation timestamp + "operators": [ + { + "address": "0x123..abfc", // ETH1 address of the operator + "enr": "enr://abcdef...12345", // Charon node ENR + "enr_signature": "0x123654...abcedf", // EIP712 Signature of ENR by ETH1 address priv key + "config_signature": "0x123456...abcdef" // EIP712 Signature of config_hash by ETH1 address priv key + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + }, + { + "address": "0x123..abfc", + "enr": "enr://abcdef...12345", + "enr_signature": "0x123654...abcedf", + "config_signature": "0x123456...abcdef" + } + ], + "definition_hash": "0xabcdef...abcedef", // Final hash of all fields + "validators": [ + { + "fee_recipient_address": "0x123..abfc", // ETH1 fee_recipient address of validator + "withdrawal_address": "0x123..abfc" // ETH1 withdrawal address of validator + } + ], + "deposit_amounts": [ + "32000000000" + ] +} +``` + +### Using the DV Launchpad + +* A `leader/creator`, that wishes to coordinate the creation of a new Distributed Validator Cluster navigates to the launchpad and selects "Create new Cluster". +* The `leader/creator` uses the user interface to configure all of the important details about the cluster including: + * The `Withdrawal Address` for the created validators; + * The `Fee Recipient Address` for block proposals if it differs from the withdrawal address; + * The number of distributed validators to create; + * The list of participants in the cluster specified by Ethereum address(/ENS); + * The threshold of fault tolerance required. +* These key pieces of information form the basis of the cluster configuration. These fields (and some technical fields like DKG algorithm to use) are serialized and merklized to produce the definition's `cluster_definition_hash`. This merkle root will be used to confirm that there is no ambiguity or deviation between definitions when they are provided to Charon nodes. +* Once the `leader/creator` is satisfied with the configuration they publish it to the launchpad's data availability layer for the other participants to access. (For early development the launchpad will use a centralised backend db to store the cluster configuration. Near production, solutions like IPFS or arweave may be more suitable for the long-term decentralisation of the launchpad.) + +## Cluster Lock File + +The `cluster-lock.json` has the following schema: + +```json +{ + "cluster_definition": {...}, // Cluster definition json, identical schema to above, + "distributed_validators": [ // Length equal to cluster_definition.num_validators. + { + "distributed_public_key": "0x123..abfc", // DV root pubkey + "public_shares": [ "abc...fed", "cfd...bfe"], // Length equal to cluster_definition.operators + "partial_deposit_data": [ + { + "pubkey": "0x123..abfc", + "withdrawal_credentials": "0x123..abfc", + "amount": "32000000000", + "signature": "0x123456...abcdef", + "deposit_data_root": "0x123456...abcdef" + } + ], + "builder_registration": { + "message": { + "fee_recipient": "0x123456...abcdef", + "gas_limit": 30000000, + "timestamp": 1696000704, + "pubkey": "0x123456...abcdef" + }, + "signature": "0x123456...abcdef" + } + } + ], + "signature_aggregate": "abcdef...abcedef", // BLS aggregate signature of the lock hash signed by each DV pubkey. + "lock_hash": "abcdef...abcedef", // definition_hash plus distributed_validators + "node_signatures": [ + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef", + "0x123456...abcdef" + ] +} +``` + +## Cluster Size and Resilience + +The cluster size (the number of nodes/operators in the cluster) determines the resilience of the cluster; its ability to remain operational under diverse failure scenarios. Larger clusters can tolerate more faulty nodes. However, increased cluster size implies higher operational costs and potential network latency, which may negatively affect performance. + +Optimal cluster size is therefore a trade-off between resilience (larger is better) vs cost-efficiency and performance (smaller is better). + +Cluster resilience can be broadly classified into two categories: + +* [**Byzantine Fault Tolerance (BFT)**](https://en.wikipedia.org/wiki/Byzantine_fault) - the ability to tolerate nodes that are actively trying to disrupt the cluster. +* [**Crash Fault Tolerance (CFT)**](https://en.wikipedia.org/wiki/Fault_tolerance) - the ability to tolerate nodes that have crashed or are otherwise unavailable. + +Different cluster sizes tolerate different counts of byzantine vs crash nodes. In practice, hardware and software crash relatively frequently, while byzantine behaviour is relatively uncommon. However, Byzantine Fault Tolerance is crucial for trust minimised systems like distributed validators. Thus, cluster size can be chosen to optimise for either BFT or CFT. + +The table below lists different cluster sizes and their characteristics: + +* `Cluster Size` - the number of nodes in the cluster. +* `Threshold` - the minimum number of nodes that must collaborate to reach consensus quorum and to create signatures. +* `BFT #` - the maximum number of byzantine nodes that can be tolerated. +* `CFT #` - the maximum number of crashed nodes that can be tolerated. + +| Cluster Size | Threshold | BFT # | CFT # | Note | +| ------------ | --------- | ----- | ----- | ---------------------------------- | +| 1 | 1 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 2 | 2 | 0 | 0 | ❌ Invalid: Not CFT nor BFT! | +| 3 | 2 | 0 | 1 | ⚠️ Warning: CFT but not BFT! | +| 4 | 3 | 1 | 1 | ✅ CFT and BFT optimal for 1 faulty | +| 5 | 4 | 1 | 1 | | +| 6 | 4 | 1 | 2 | ✅ CFT optimal for 2 crashed | +| 7 | 5 | 2 | 2 | ✅ BFT optimal for 2 byzantine | +| 8 | 6 | 2 | 2 | | +| 9 | 6 | 2 | 3 | ✅ CFT optimal for 3 crashed | +| 10 | 7 | 3 | 3 | ✅ BFT optimal for 3 byzantine | +| 11 | 8 | 3 | 3 | | +| 12 | 8 | 3 | 4 | ✅ CFT optimal for 4 crashed | +| 13 | 9 | 4 | 4 | ✅ BFT optimal for 4 byzantine | +| 14 | 10 | 4 | 4 | | +| 15 | 10 | 4 | 5 | ✅ CFT optimal for 5 crashed | +| 16 | 11 | 5 | 5 | ✅ BFT optimal for 5 byzantine | +| 17 | 12 | 5 | 5 | | +| 18 | 12 | 5 | 6 | ✅ CFT optimal for 6 crashed | +| 19 | 13 | 6 | 6 | ✅ BFT optimal for 6 byzantine | +| 20 | 14 | 6 | 6 | | +| 21 | 14 | 6 | 7 | ✅ CFT optimal for 7 crashed | +| 22 | 15 | 7 | 7 | ✅ BFT optimal for 7 byzantine | + +The table above is determined by the QBFT consensus algorithm with the following formulas from [this](https://arxiv.org/pdf/1909.10194.pdf) paper: + +```shell +n = cluster size + +Threshold: min number of honest nodes required to reach quorum given size n +Quorum(n) = ceiling(2n/3) + +BFT #: max number of faulty (byzantine) nodes given size n +f(n) = floor((n-1)/3) + +CFT #: max number of unavailable (crashed) nodes given size n +crashed(n) = n - Quorum(n) +``` diff --git a/versioned_docs/version-v1.9/learn/charon/dkg.md b/versioned_docs/version-v1.9/learn/charon/dkg.md new file mode 100644 index 0000000000..5f7acf9daa --- /dev/null +++ b/versioned_docs/version-v1.9/learn/charon/dkg.md @@ -0,0 +1,73 @@ +--- +description: "Generating private keys for a Distributed Validator requires a Distributed Key Generation (DKG) Ceremony." +sidebar_label: "Distributed Key Generation" +slug: /learn/charon/dkg +--- + +# Distributed Key Generation + +## Overview + +A [**distributed validator key**](../intro/key-concepts.md#distributed-validator-key) is a group of BLS private keys that together operate as a threshold key for participating in proof-of-stake consensus. + +To make a distributed validator with no fault-tolerance (i.e. all nodes need to be online to sign every message), due to the BLS signature scheme used by Proof of Stake Ethereum, each key share could be chosen by operators independently. However, to create a distributed validator that can stay online despite a subset of its nodes going offline, the key shares need to be generated together (4 randomly chosen points on a graph don't all necessarily sit on the same order three curve). To do this in a secure manner with no one party being trusted to distribute the keys requires what is known as a [**distributed key generation ceremony**](../intro/key-concepts.md#distributed-validator-key-generation-ceremony). + +The Charon client has the responsibility of securely completing a distributed key generation ceremony with its counterparty nodes. The ceremony configuration is outlined in a [cluster definition](cluster-configuration.md). + +## Actors Involved + +A distributed key generation ceremony involves `Operators` and their `Charon clients`. + +* An `Operator` is identified by their Ethereum address. They will sign a message with this address to authorize their Charon client to take part in the DKG ceremony. +* A `Charon client` is also identified by a public/private key pair, in this instance, the public key is represented as an [Ethereum Node Record](https://eips.ethereum.org/EIPS/eip-778) (ENR). This is a standard identity format for both EL and CL clients. These ENRs are used by each Charon node to identify its cluster peers over the internet, and to communicate with one another in an [end to end encrypted manner](https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise). These keys need to be created (and backed up) by each operator before they can participate in a cluster creation. + +## Cluster Definition Creation + +This cluster definition specifies the intended cluster configuration before keys have been created in a distributed key generation ceremony. The `cluster-definition.json` file can be created with the help of the [Distributed Validator Launchpad](cluster-configuration.md#using-the-dv-launchpad) or via the [CLI](cluster-configuration.md#using-the-cli). + +## Carrying out the DKG ceremony + +Once all participants have signed the cluster definition, they can load the `cluster-definition` file into their Charon client, and the client will attempt to complete the DKG. + +Charon will read the ENRs in the definition, confirm that its ENR is present, and then will reach out to relays that are deployed to find the other ENRs on the network. (Fresh ENRs just have a public key and an IP address of 0.0.0.0 until they are loaded into a live Charon client, which will update the IP address and increment the ENR's nonce and resign with the client's private key. If an ENR with a higher nonce is seen by a Charon client, they will update the IP address of that ENR in their address book.) + +Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the ceremony begins. + +No user input is required, Charon does the work and outputs the following files to each machine and then exits. + +## Backing up the ceremony artifacts + +At the end of a DKG ceremony, each operator will have a number of files outputted by their Charon client based on how many distributed validators the group chose to generate together. + +These files are: + +* **Validator keystore(s):** These files will be loaded into the operator's validator client and each file represents one share of a Distributed Validator. +* **A distributed validator cluster lock file:** This `cluster-lock.json` file contains the configuration a distributed validator client like Charon needs to join a cluster capable of operating a number of distributed validators. +* **Validator deposit data:** This file is used to activate one or more distributed validators on the Ethereum network. + +Once the ceremony is complete, all participants should take a backup of the created files. In future versions of Charon, if a participant loses access to these key shares, it will be possible to use a key re-sharing protocol to swap the participant's old keys out of a distributed validator in favour of new keys, allowing the rest of a cluster to recover from a set of lost key shares. However for now, without a backup, the safest thing to do would be to exit the validator. + +## DKG Verification + +For many use cases of distributed validators, the funder/depositor of the validator may not be the same person as the key creators/node operators, as (outside of the base protocol) stake delegation is a common phenomenon. This handover of information introduces a point of trust. How does someone verify that a proposed validator `deposit data` corresponds to a real, fair, DKG with participants the depositor expects? + +There are a number of aspects to this trust surface that can be mitigated with a "Don't trust, verify" model. Verification for the time being is easier off chain, until things like a [BLS precompile](https://eips.ethereum.org/EIPS/eip-2537) are brought into the EVM, along with cheap ZKP verification on chain. Some of the questions that can be asked of Distributed Validator Key Generation Ceremonies include: + +* Do the public key shares combine together to form the group public key? + * This can be checked on chain as it does not require a pairing operation + * This can give confidence that a BLS pubkey represents a Distributed Validator, but does not say anything about the custody of the keys. (e.g. Was the ceremony sybil attacked, did they collude to reconstitute the group private key etc.) +* Do the created BLS public keys attest to their `cluster_definition_hash`? + * This is to create a backwards link between newly created BLS public keys and the operator's eth1 addresses that took part in their creation. + * If a proposed distributed validator BLS group public key can produce a signature of the `cluster_definition_hash`, it can be inferred that at least a threshold of the operators signed this data. + * As the `cluster_definition_hash` is the same for all distributed validators created in the ceremony, the signatures can be aggregated into a group signature that verifies all created group keys at once. This makes it cheaper to verify a number of validators at once on chain. +* Is there either a VSS or PVSS proof of a fair DKG ceremony? + * VSS (Verifiable Secret Sharing) means only operators can verify fairness, as the proof requires knowledge of one of the secrets. + * PVSS (Publicly Verifiable Secret Sharing) means anyone can verify fairness, as the proof is usually a Zero Knowledge Proof. + * A PVSS of a fair DKG would make it more difficult for operators to collude and undermine the security of the Distributed Validator. + * Zero Knowledge Proof verification on chain is currently expensive, but is becoming achievable through the hard work and research of the many ZK based teams in the industry. + +## Appendix + +### Sample Configuration and Lock Files + +Refer to the details [here](cluster-configuration.md). diff --git a/versioned_docs/version-v1.9/learn/charon/intro.md b/versioned_docs/version-v1.9/learn/charon/intro.md new file mode 100644 index 0000000000..2859a36898 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/charon/intro.md @@ -0,0 +1,69 @@ +--- +description: "Charon - The Distributed Validator Client" +sidebar_label: "Introduction to Charon" +slug: /learn/charon/intro +--- + +# Introduction to Charon + +This section introduces and outlines the Charon _\[kharon]_ middleware, Obol's implementation of DVT. Please see the [key concepts](../intro/key-concepts.md) section as background and context. + +## What is Charon? + +Charon is a GoLang-based, HTTP middleware built by Obol to enable any existing Ethereum validator clients to operate together as part of a distributed validator. + +Charon sits as a middleware between a normal validating client and its connected beacon node, intercepting and proxying API traffic. Multiple Charon clients are configured to communicate together to come to consensus on validator duties and behave as a single unified proof-of-stake validator together. The nodes form a cluster that is _byzantine-fault tolerant_ and continues to progress assuming a supermajority of working/honest nodes is met. + +![](/img/gitbook/image-20-1.png) + +## Charon Architecture + +Charon is an Ethereum proof of stake distributed validator (DV) client. Like any validator client, its main purpose is to perform validation duties for the Beacon Chain, primarily attestations and block proposals. The beacon client handles a lot of the heavy lifting, leaving the validator client to focus on fetching duty data, signing that data, and submitting it back to the beacon client. + +Charon is designed as a generic event-driven workflow with different components coordinating to perform validation duties. All duties follow the same flow, the only difference being the signed data. The workflow can be divided into phases consisting of one or more components: + +![](/img/gitbook/image-21.png) + +### Determine **when** duties need to be performed + +The beacon chain is divided into [slots](https://eth2book.info/capella/part3/config/types/#slot) and [epochs](https://eth2book.info/capella/part3/config/types/#epoch), which divides it into deterministically fixed-size time chunks. The first step is to determine when (which slot/epoch) duties need to be performed. This is done by the `scheduler` component. It queries the beacon node to detect which validators defined in the cluster lock are active, and what duties they need to perform for the upcoming epoch and slots. When such a slot starts, the `scheduler` emits an event indicating which validator needs to perform what duty. + +### Fetch and come to consensus on **what** data to sign + +A DV cluster consists of multiple operators each provided with one of the M-of-N threshold BLS private key shares per validator. The key shares are imported into the validator clients which produce partial signatures. Charon threshold aggregates these partial signatures before broadcasting them to the Beacon Chain. _But to threshold aggregate partial signatures, each validator must sign the same data._ The cluster must therefore coordinate and come to a consensus on what data to sign. + +`Fetcher` fetches the unsigned duty data from the beacon node upon receiving an event from `Scheduler`. For attestations, this is the unsigned attestation, for block proposals, this is the unsigned block. + +The `Consensus` component listens to events from Fetcher and starts a [QBFT](https://docs.goquorum.consensys.net/configure-and-manage/configure/consensus-protocols/qbft/) consensus game with the other Charon nodes in the cluster for that specific duty and slot. When consensus is reached, the resulting unsigned duty data is stored in the `DutyDB`. + +### **Wait** for the VC to sign + +Charon is a **middleware** distributed validator client. That means Charon doesn’t have access to the validator private key shares and cannot sign anything on demand. Instead, operators import the key shares into industry-standard validator clients (VC) that are configured to connect to their local Charon client instead of their local Beacon node directly. + +Charon, therefore, serves the [Ethereum Beacon Node API](https://ethereum.github.io/beacon-APIs/#/) from the `ValidatorAPI` component and intercepts some endpoints while proxying other endpoints directly to the upstream Beacon node. + +The VC queries the `ValidatorAPI` for unsigned data which is retrieved from the `DutyDB`. It then signs it and submits it back to the `ValidatorAPI` which stores it in the `PartialSignatureDB`. + +### **Share** partial signatures + +The `PartialSignatureDB` stores the partially signed data submitted by the local Charon client’s VC. But it also stores all the partial signatures submitted by the VCs of other peers in the cluster. This is achieved by the `PartialSignatureExchange` component that exchanges partial signatures between all peers in the cluster. All Charon clients, therefore, store all partial signatures the cluster generates. + +### **Threshold Aggregate** partial signatures + +The `SignatureAggregator` is invoked as soon as sufficient (any M of N) partial signatures are stored in the `PartialSignatureDB`. It performs BLS threshold aggregation of the partial signatures resulting in a final signature that is valid for the beacon chain. + +### **Broadcast** final signature + +Finally, the `Broadcaster` component broadcasts the final threshold aggregated signature to the Beacon client, thereby completing the duty. + +### Ports + +The following is an outline of the services that can be exposed by Charon. + +* **:3600** - The validator REST API. This is the port that serves the consensus layer's [beacon node API](https://ethereum.github.io/beacon-APIs/). This is the port validator clients should talk to instead of their standard consensus client REST API port. Charon subsequently proxies these requests to the upstream consensus client specified by `--beacon-node-endpoints`. +* **:3610** - Charon P2P port. This is the port that Charon clients use to communicate with one another via TCP. This endpoint should be port-forwarded on your router and exposed publicly, preferably on a static IP address. This IP address should then be set on the charon run command with `--p2p-external-ip` or `CHARON_P2P_EXTERNAL_IP`. +* **:3620** - Monitoring port. This port hosts a webserver that serves Prometheus metrics on `/metrics`, a readiness endpoint on `/readyz` and a liveness endpoint on `/livez`, and a pprof server on `/debug/pprof`. This port should not be exposed publicly. + +## Getting started + +For more information on running Charon, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). diff --git a/versioned_docs/version-v1.9/learn/further-reading/README.md b/versioned_docs/version-v1.9/learn/further-reading/README.md new file mode 100644 index 0000000000..6f13128d79 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/further-reading/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Further Reading" +slug: /learn/further-reading +--- + +# Further Reading + diff --git a/versioned_docs/version-v1.9/learn/further-reading/ethereum_and_dvt.md b/versioned_docs/version-v1.9/learn/further-reading/ethereum_and_dvt.md new file mode 100644 index 0000000000..45e6731817 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/further-reading/ethereum_and_dvt.md @@ -0,0 +1,55 @@ +--- +description: "Ethereum and its relationship with DVT" +sidebar_label: "Ethereum and Its Relationship With DVT" +slug: /learn/further-reading/ethereum_and_dvt +--- + +# Ethereum and Its Relationship With DVT + +Our goal for this page is to equip you with the foundational knowledge needed to actively contribute to the advancement of Obol while also directing you to valuable Ethereum and DVT related resources. Additionally, we will shed light on the intersection of DVT and Ethereum, offering curated articles and blog posts to enhance your understanding. + +## **Understanding Ethereum** + +To grasp the current landscape of Ethereum's PoS development, we encourage you to delve into the wealth of information available on the [Official Ethereum Website.](https://ethereum.org/en/learn/) The Ethereum website serves as a hub for all things Ethereum, catering to individuals at various levels of expertise, whether you're just starting your journey or are an Ethereum veteran. Here, you'll find a trove of resources that cater to diverse learning needs and preferences, ensuring that there's something valuable for everyone in the Ethereum community to discover. + +## **DVT & Ethereum** + +### Distributed Validator Technology + +> "Distributed validator technology (DVT) is an approach to validator security that spreads out key management and signing responsibilities across multiple parties, to reduce single points of failure, and increase validator resiliency. +> +> It does this by splitting the private key used to secure a validator across many computers organized into a "cluster". The benefit of this is that it makes it very difficult for attackers to gain access to the key, because it is not stored in full on any single machine. It also allows for some nodes to go offline, as the necessary signing can be done by a subset of the machines in each cluster. This reduces single points of failure from the network and makes the whole validator set more robust." _(ethereum.org, 2023)_ + +#### Learn More About Distributed Validator technology from [The Official Ethereum Website](https://ethereum.org/en/staking/dvt/) + +### How Does DVT Improve Staking on Ethereum? + +If you haven’t yet heard, Distributed Validator Technology, or DVT, is the next big thing on The Merge section of the Ethereum roadmap. Learn more about this in our blog post: [What is DVT and How Does It Improve Staking on Ethereum?](https://blog.obol.tech/what-is-dvt-and-how-does-it-improve-staking-on-ethereum/)\ +\ +\&#xNAN;_**Vitalik's Ethereum Roadmap:**_ + +![](/img/gitbook/image-84.png) + +### Deep Dive Into DVT and Charon’s Architecture + +Minimizing correlation is vital when designing DVT as Ethereum Proof of Stake is designed to heavily punish correlated behavior. In designing Obol, we’ve made careful choices to create a trust-minimized and non-correlated architecture. + +[**Read more about Designing Non-Correlation Here**](https://blog.obol.tech/deep-dive-into-dvt-and-charons-architecture/) + +### Performance Testing Distributed Validators + +In our mission to help make Ethereum consensus more resilient and decentralised with distributed validators (DVs), it’s critical that we do not compromise on the performance and effectiveness of validators. Earlier this year, we worked with MigaLabs, the blockchain ecosystem observatory located in Barcelona, to perform an independent test to validate the performance of Obol DVs under different configurations and conditions. After taking a few weeks to fully analyse the results together with MigaLabs, we’re happy to share the results of these performance tests. + +[**Read More About The Performance Test Results Here**](https://blog.obol.tech/performance-testing-distributed-validators/) + +![](/img/gitbook/image-24.png) + +### More Resources + +* [Sorting out Distributed Validator Technology](https://medium.com/nethermind-eth/sorting-out-distributed-validator-technology-a6f8ca1bbce3) +* [A tour of Verifiable Secret Sharing schemes and Distributed Key Generation protocols](https://medium.com/nethermind-eth/a-tour-of-verifiable-secret-sharing-schemes-and-distributed-key-generation-protocols-3c814e0d47e1) +* [Threshold Signature Schemes](https://medium.com/nethermind-eth/threshold-signature-schemes-36f40bc42aca) + +#### References + +* ethereum.org. (2023). Distributed Validator Technology. \[online] Available at: https://ethereum.org/en/staking/dvt/ \[Accessed 25 Sep. 2023]. diff --git a/versioned_docs/version-v1.9/learn/further-reading/peer_score.md b/versioned_docs/version-v1.9/learn/further-reading/peer_score.md new file mode 100644 index 0000000000..e79156eb98 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/further-reading/peer_score.md @@ -0,0 +1,48 @@ +--- +description: "Measuring Individual Performance in Distributed Validators" +sidebar_label: "Peer Score" +slug: /learn/further-reading/peer_score +--- + +# Peer Score + +## Introduction + +Validator effectiveness is a critical metric for assessing the health of a rated network. It determines how well validators perform their attestation and block proposal duties. Existing solutions, like RAVER (Rated Validator Effectiveness Rating), provide a effectiveness score of a validator. In a monolithic validator that is run by a single operator, validator effectiveness can be considered as a proxy for the effectiveness or “score” of that operator. However, this approach falls short when dealing with distributed validators (DVs) maintained by multiple operators. + +Peer Score v0 addresses this limitation by introducing a method to evaluate the performance of individual operators within a DV. This enables a more granular assessment of contribution within a distributed setting. + +## Key Concepts + +* **Distributed Validator (DV):** A validator maintained by a group of operators in a fault-tolerant manner. +* **Peer:** An individual operator contributing to a DV. +* **Peer Score:** A metric reflecting the performance of a peer within a DV, calculated as the ratio of completed duties to expected duties. +* **Operator Score:** An aggregated metric representing the overall effectiveness of an operator across multiple DVs (planned for future iterations). + +## Challenges with RAVER in DVs + +RAVER assigns a single effectiveness score to the entire DV. This score doesn't reflect the individual contributions of operators within the group. For example, a DV with 95% effectiveness maintained by four operators (A, B, C, and D) doesn't guarantee that each operator has a 95% effectiveness score. It's possible that even if operator D is frequently offline, the remaining operators (A, B, and C) can maintain the overall DV effectiveness. + +## Peer Score v0 Calculation + +Peer Score v0 utilizes a straightforward formula: + +`Peer Score = (Total duties completed by peer) / (Total duties expected by peer)` + +This ratio reflects the peer's adherence to its assigned duties within the DV. + +## Future Iterations + +Peer Score v0 lays the foundation for a more comprehensive evaluation system. Planned advancements include: + +* **Weighted Duties:** Assigning varying weights to different duties based on their significance to the network. +* **Decentralization Scores:** Integrating metrics that consider the decentralization of clients and operator locations. +* Peer rating: an anonymous rating peers can give to their other peers to grade their social co-ordination. + +## Use Cases + +Peer Score offers valuable insights for various stakeholders: + +* **Staking/Restaking Protocols:** Peer Score is crucial component of Obol’s Techne Credential Program. LSPs and LRPs can utilize Techne Credentials ,and hence Peer Score, to identify efficient operators for expanding their operator sets. +* **DV Operators:** Forming operator collectives based on peer effectiveness and potentially removing underperforming peers from DVs (with Charon v2 cluster mutability). +* **DV Software Developers:** Establishing a standardized metric for evaluating operator performance across various DV software, enabling the development of new tools and services. diff --git a/versioned_docs/version-v1.9/learn/further-reading/resources.md b/versioned_docs/version-v1.9/learn/further-reading/resources.md new file mode 100644 index 0000000000..dbd5286202 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/further-reading/resources.md @@ -0,0 +1,59 @@ +--- +description: "A collection of links to products and content relating to Distributed Validators." +sidebar_label: "Useful Links" +slug: /learn/further-reading/resources +--- + +# Useful Links + +The following is a curated list of the best internal and external resources for using, creating, running, building, and researching Distributed Validators. To add to this list, please open a [pull request](https://github.com/ObolNetwork/obol-docs/pulls/). + +## Deposit Interfaces + +* [Chorus One](https://opus.chorus.one/pool/stake/) +* [Stakely](https://obol-portal.stakely.io/) +* [Mellow](https://app.mellow.finance/restake/ethereum-dvsteth) + +## Launchers and Deployment Tooling + +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../../run-a-dv/start/create-a-dv-alone.mdx) +* [Run a DV as a group](../../run-a-dv/start/create-a-dv-with-a-group.mdx) +* [Run a DV using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) + +## Security and Best Practices + +* [Audits](https://github.com/ObolNetwork/obol-security/tree/main/audits) +* [Security repo](https://github.com/ObolNetwork/obol-security) +* [Security Docs Page](../../advanced-and-troubleshooting/security/overview.md) +* [Best practices doc](../../run-a-dv/prepare/deployment-best-practices.md) +* [Status Page](https://status.obol.org/) + +## Security Audits and Assessments + +* A [review](../../advanced-and-troubleshooting/security/ev-assessment.md) of Obol Labs development processes by Ethereal Ventures +* A [security assessment](https://github.com/ObolNetwork/obol-security/blob/f9d7b0ad0bb8897f74ccb34cd4bd83012ad1d2b5/audits/Sigma_Prime_Obol_Network_Charon_Security_Assessment_Report_v2_1.pdf) of Charon by [Sigma Prime](https://sigmaprime.io/). +* A [solidity audit](../../advanced-and-troubleshooting/security/smart-contract-audit.md) of the Obol Splits contracts by [Zach Obront](https://zachobront.com/). +* [Charon Threat model](../../advanced-and-troubleshooting/security/threat_model.md) +* [QuantStamp Charon audit Q4 2023](https://obol.tech/charon_quantstamp_assessment.pdf) + +## Research and Development + +* Nethermind research papers via the [Obol Network Research Forum](https://community.obol.tech/?ref=blog.obol.org) + * [Publicly Verifiable Secret Sharing-based Distributed Key Generation](https://community.obol.tech/t/proposal-publicly-verifiable-secret-sharing-based-distributed-key-generation/94?ref=blog.obol.org) + * [Key Refresh Scheme for DV operators](https://community.obol.tech/t/proposal-key-refresh-scheme-for-dv-operators/97?ref=blog.obol.org) + * [BFT protocol that can mutate its operator set in a byzantine setting](https://community.obol.tech/t/proposal-bft-protocol-that-can-mutate-its-operator-set-in-a-byzantine-setting/106?ref=blog.obol.org) + * [Using DV clusters for encrypted transaction mempools](https://community.obol.tech/t/proposal-using-dv-clusters-for-encrypted-transaction-mempools/108?ref=blog.obol.org) + * Attributable Consensus Solution for DV Clusters [Part I](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters/104?ref=blog.obol.org), [Part II](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-2/107?ref=blog.obol.org), [Part III](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-part-3/109?ref=blog.obol.org), [Appendix](https://community.obol.org/t/proposal-attributable-consensus-solution-for-dv-clusters-appendix/110?ref=blog.obol.org) +* [Obol-Lido Splits Dune Dashboard](https://dune.com/obol_labs/lido-splits) diff --git a/versioned_docs/version-v1.9/learn/further-reading/testnet.md b/versioned_docs/version-v1.9/learn/further-reading/testnet.md new file mode 100644 index 0000000000..9e69963aa5 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/further-reading/testnet.md @@ -0,0 +1,190 @@ +--- +description: "Community testing efforts" +sidebar_label: "Community Testing" +slug: /learn/further-reading/testnet +--- + +# Community Testing + +## Community Testing + +:::tip +This page looks at the community testing efforts organised by Obol to test Distributed Validators at scale. If you are looking for guides to run a Distributed Validator on testnet you can do so [here](../../run-a-dv/start/quickstart_overview.md). +::: + +Over the last number of years, DV Labs has coordinated and hosted progressively larger testing efforts to help harden the Charon client and iterate on the key generation tooling. + +Below is a breakdown of the testing initiatives, the features targeted for completion in each testnet, along with their respective completion dates and durations. + +## Testing Programs on Testnet + +Listed from most recent to oldest: + +* [x] [Lido Testnet 3 - SimpleDVT](testnet.md#lido-testnet-wave-3---simpledvt) +* [x] [Lido Testnet 2](testnet.md#lido-testnet-wave-2) +* [x] [Lido Testnet 1 - Pilot](testnet.md#lido-testnet-wave-1---pilot) +* [x] [Bia Public Testnet 2](testnet.md#bia-public-testnet-2) +* [x] [Athena Public Testnet 1](testnet.md#athena-public-testnet-1) +* [x] [Dev Net 2](testnet.md#devnet-2) +* [x] [Dev Net 1](testnet.md#devnet-1) + +### Lido Testnet Wave 3 - SimpleDVT + +Official report [available here](https://obol.org/lido_obol_3.pdf). The metrics presented were derived from a 45-day monitoring period starting on November 18th, 2023. Each cluster initially ran 5 validators, a number that was subsequently scaled up to 50 and then 100 for most clusters. Throughout the testing, various challenges were encountered, primarily stemming from infrastructure limitations due to the early-stage development of the Holesky testnet. Throughout this monitoring phase, the aggregate metrics of Obol DVT clusters surpassed both Lido’s minimum requirements and the Holesky network averages. + +**Participants:** Professional and community operators. Initially 214 participants, which later fell to 196. + +**State:** Pre-release + +**Network:** Holesky + +**Completed date:** Jan 11th, 2024 + +**Duration:** 2 months (Nov 28th, 2023 - Jan 11th, 2024) + +**Goals:** + +* Engage a broad set of node operators. +* Operate a high number of validators on each cluster. +* Gather performance data on potential candidates for Lido SimpleDVT onboarding. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 2 + +Official report [available here](https://obol.org/lido_obol_2.pdf). Our testing period spanned 59 days, from March 23rd to May 20th, 2023. During this time, we focused on key metrics for our Lido clusters, also drawing comparisons with industry peers. We're excited to share that the data displays strong performance of our DVT clusters as we continue to improve and enhance our middleware client, Charon. + +**Participants:** >50 community professional and community node operators. + +**State:** MVP + +**Network:** Görli + +**Completed date:** May 2023 + +**Duration:** 3 months (March - May 2023) + +**Goals:** + +* Engage a broad set of node operators. +* Conduct large-scale testing within Lido's framework. +* Demonstrate good performance, even with a large degree of geographic, client, and hardware diversity. + +### Lido Testnet Wave 1 - Pilot + +Offical report [available here](https://obol.org/lido_obol_1.pdf).Gathered key metrics from our Lido clusters, benchmarking these metrics against other industry players, showing strong results and reaffirming our confidence in the future of the technology. + +**Participants:** Professional node operators: Hashquark, CryptoManufaktur, Nethermind, Simply Staking, DSRV, Kukis Global, Chorus One, Staking Facilities, Blockscape, Everstake, Stakely. + +**State:** MVP + +**Network:** Görli + +**Completed date:** January 2023 + +**Duration:** 104 days (Oct 3rd, 2022 - Jan 15th, 2023) + +**Goals:** + +* Engage Lido and Lido node operators with DVT. +* Assist Lido to build out a testing program framework with can be repeated at a larger scale. +* Test up to 1000 active validators within each cluster. + +### Bia Public Testnet 2 + +This second public testnet intends to take the learning from Athena and scale the network by engaging both the wider at-home validator community and professional operators. This is the first time users are setting up DVs using the DV launchpad. + +This testnet is also important for learning the conditions Charon will be subjected to in production. A core output of this testnet is a large number of autonomous public DV clusters running and building up the Obol community with technical ambassadors. + +**Participants:** Obol Community, Ethereum staking community + +**State:** MVP + +**Network:** Görli + +**Completed date:** March 2023 + +**Duration:** 2 weeks cluster setup, 4-8 weeks operation + +**Goals:** + +* Engage the wider Solo and Professional Ethereum Staking Community. +* Get integration feedback. +* Build confidence in Charon after running DVs on an Ethereum testnet. +* Learn about the conditions Charon will be subjected to in production. +* Distributed Validator returns are competitive versus single validator clients. +* Make deploying Ethereum validator nodes accessible using the DV Launchpad. +* Build comprehensive guides for various profiles to spin up DVs with minimal supervision from the core team. + +### Athena Public Testnet 1 + +With tutorials for solo and group flows having been developed and refined. The goal for public testnet 1 was to get distributed validators into the hands of the wider Obol Community for the first time. The core focus of this testnet was the onboarding experience. + +The core output from this testnet was a significant number of public cluster running and public feedback collected. + +This was an unincentivized testnet and formed the basis for us to figure out a Sybil resistance mechanism. + +**Participants:** Obol Community + +**State:** Bare Minimum + +**Network:** Görli + +**Completed date:** October 2022 + +**Duration:** 2 weeks cluster setup, 8 weeks operation + +**Goals:** + +* Get distributed validators into the hands of the Obol Early Community for the first time. +* Create the first public onboarding experience and gather feedback. This is the first time we need to provide comprehensive instructions for as many platforms (Unix, Mac, Windows) as possible. +* Make deploying Ethereum validator nodes accessible using the CLI. +* Generate a backlog of bugs, feature requests, platform requests and integration requests. + +### Devnet 2 + +The second devnet aimed to have a number of trusted operators test out our earliest tutorial flows **together** for the first time. + +The aim was for groups of 4 testers to complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients and 4 different validator clients (Lighthouse, Teku, Lodestar and Vouch), each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. + +This devnet was the first time `charon dkg` was tested with users. A core focus of this devnet was to collect network performance data. + +This was also the first time Charon was run in variable, non-virtual networks (i.e. the real internet). + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** July 2022 + +**Duration:** 2 weeks + +**Goals:** + +* Groups of 4 testers complete a group onboarding tutorial, using `docker compose` to spin up 4 Charon clients, each on their own machine located either at the operator's home or a location of their choice, while running at least a kiln consensus client. +* Operators avoid exposing Charon to the public internet on a static IP address through the use of Obol-hosted relay nodes. +* Users test `charon dkg`. The launchpad is not used, and this dkg is triggered by a manifest config file created locally by a single operator using the `charon create dkg` command. +* Effective collection of network performance data, to enable gathering even higher signal performance data at scale during public testnets. +* Block proposals are in place. + +### Devnet 1 + +The first devnet aimed to have a number of trusted operators test out our earliest tutorial flows. The aim was for a single user to complete the tutorials alone, using `docker compose` to spin up 4 Charon clients, and 4 different validator clients on a single machine, using a remote consensus client. The keys were created locally in Charon and activated with the existing launchpad. + +**Participants:** Obol Dev Team, Client team advisors. + +**State:** Pre-product + +**Network:** Kiln + +**Completed Date:** June 2022 + +**Duration:** 1 week + +**Goals:** + +* A single user completes the first tutorial alone, using `docker compose` to spin up 4 Charon clients on a single machine, with a remote consensus client. The keys are created locally in Charon and activated with the existing launchpad. +* Prove that the distributed validator paradigm with 4 separate VC implementations together operating as one logical validator works. +* Establish basic monitoring systems in preparation for the next testnet, where accurate monitoring will be crucial as Charon operates across a network. diff --git a/versioned_docs/version-v1.9/learn/intro/README.md b/versioned_docs/version-v1.9/learn/intro/README.md new file mode 100644 index 0000000000..3bbd45754b --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/README.md @@ -0,0 +1,27 @@ +--- +title: "Introduction" +description: "Documentation, integration guides, and protocol specifications" +sidebar_label: "README" +slug: /learn/intro/intro +unlisted: true +--- + +## Welcome to Obol! + +Obol builds Distributed Validator Technology (DVT), which empowers node operators, staking protocols, and institutions run Ethereum validators that are more secure, fault-tolerant, and performant. DVT benefits both operators and capital allocators while strengthening the network itself by reducing centralization risk and protecting against supermajority failures. Obol DVs are the staking endgame. + +Whether you’re here to learn about DVT, integrate it into your staking stack, or want to stake your ETH on DVs, these docs will help you get started. + +--- + +## Quick start + + + + diff --git a/versioned_docs/version-v1.9/learn/intro/frequently-asked-questions.mdx b/versioned_docs/version-v1.9/learn/intro/frequently-asked-questions.mdx new file mode 100644 index 0000000000..c4be43f9c6 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/frequently-asked-questions.mdx @@ -0,0 +1,110 @@ +--- +sidebar_label: "Frequently Asked Questions" +slug: /learn/readme/frequently-asked-questions +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frequently Asked Questions + +## Frequently Asked Questions + +### General[​](frequently-asked-questions.mdx#general) {#general} +#### Does Obol have a token?[​](frequently-asked-questions.mdx#does-obol-have-a-token) {#does-obol-have-a-token} +Yes, please see the [token page](../../community-and-governance/obol-token/) for details about the OBOL Token and our [announcement](https://blog.obol.org/airdrop/) for details about the community airdrop that took place in January 2025. The official token contract address is [0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7](https://etherscan.io/token/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7). + +#### Where can I learn more about Distributed Validators?[​](frequently-asked-questions.mdx#where-can-i-learn-more-about-distributed-validators) {#where-can-i-learn-more-about-distributed-validators} +Have you checked out our [blog site](https://blog.obol.tech/) and [twitter](https://twitter.com/ObolNetwork) yet? Maybe join our [discord](https://discord.gg/n6ebKsX46w) too. + +#### Where does the name Charon come from?[​](frequently-asked-questions.mdx#where-does-the-name-charon-come-from) {#where-does-the-name-charon-come-from} +[Charon](https://www.theoi.com/Khthonios/Kharon.html) \[kharon] is the Ancient Greek Ferryman of the Dead. He was tasked with bringing people across the Acheron river to the underworld. His fee was one Obol coin, placed in the mouth of the deceased. This tradition of placing a coin or Obol in the mouth of the deceased continues to this day across the Greek world. + +#### What are the hardware requirements for running a Charon node?[​](frequently-asked-questions.mdx#what-are-the-hardware-requirements-for-running-a-charon-node) {#what-are-the-hardware-requirements-for-running-a-charon-node} +Charon alone uses negligible disk space of not more than a few MBs. However, if you are running your consensus client and execution client on the same server as Charon, then you will typically need the same hardware as running a full Ethereum node: + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 1 | 2 | +| **RAM** | 2 | 16 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 10 Mb/s | 10 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 4 | +| **RAM** | 3 | 24 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 25 Mb/s | 25 Mb/s | + + + +| | Charon + VC | Beacon Node | +| ---------------------- | ----------- | ----------- | +| **CPU\*** | 2 | 8 | +| **RAM** | 4 | 32 | +| **Storage** | 100 MB | 2 TB | +| **Internet Bandwidth** | 100 Mb/s | 100 Mb/s | + + + +\*if using vCPU, aim for 2x the above amounts + +For more hardware considerations, check out the [ethereum.org guides](https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/#environment-and-hardware) which explores various setups and trade-offs, such as running the node locally or in the cloud. + +For now, Geth, Teku & Lighthouse clients are packaged within the docker compose file provided in the [quickstart guides](../../run-a-dv/start/quickstart_overview.md), so you don't have to install anything else to run a cluster. Just make sure you give them some time to sync once you start running your node. + +#### What is the difference between a node, a validator and a cluster?[​](frequently-asked-questions.mdx#what-is-the-difference-between-a-node-a-validator-and-a-cluster) {#what-is-the-difference-between-a-node-a-validator-and-a-cluster} +A node is a single instance of Ethereum EL+CL clients that can communicate with other nodes to maintain the Ethereum blockchain. + +A validator is a node that participates in the consensus process by verifying transactions and creating new blocks. Multiple validators can run from the same node. + +A cluster is a group of nodes that act together as one or several validators which allows for a more efficient use of resources, reduces operational costs, and provides better reliability and fault tolerance. + +#### Can I migrate an existing Charon node to a new machine?[​](frequently-asked-questions.mdx#can-i-migrate-an-existing-charon-node-to-a-new-machine) {#can-i-migrate-an-existing-charon-node-to-a-new-machine} +It is possible to migrate your Charon node to another machine running the same config by moving the `.charon` folder with its contents to your new machine. Make sure the EL and CL on the new machine are synced before proceeding to the move to minimize downtime. + +### Distributed Key Generation[​](frequently-asked-questions.mdx#distributed-key-generation) {#distributed-key-generation} +#### What are the min and max numbers of operators for a Distributed Validator?[​](frequently-asked-questions.mdx#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator) {#what-are-the-min-and-max-numbers-of-operators-for-a-distributed-validator} +Currently, the minimum is 4 operators with a threshold of 3. + +The threshold (aka quorum) corresponds to the minimum number of operators that need to be active for the validator(s) to be able to perform its duties. It is defined by the following formula `n-(ceil(n/3)-1)`. We strongly recommend using this default threshold in your DKG as it maximises liveness while maintaining BFT safety. Setting a 4 out of 4 cluster for example, would make your validator more vulnerable to going offline instead of less vulnerable. You can check the recommended threshold values for a cluster [here](key-concepts.md#distributed-validator-threshold). + +### Obol Splits[​](frequently-asked-questions.mdx#obol-splits) {#obol-splits} +#### What are Obol Splits?[​](frequently-asked-questions.mdx#what-are-obol-splits) {#what-are-obol-splits} +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido, Eigenlayer, and in the future a number of other LSPs. + +#### Are Obol Splits non-custodial?[​](frequently-asked-questions.mdx#are-obol-splits-non-custodial) {#are-obol-splits-non-custodial} +Yes. Unless you were to decide to [deploy an editable splitter contract](frequently-asked-questions.mdx#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. + +#### Can I change the percentages in a split?[​](frequently-asked-questions.mdx#can-i-change-the-percentages-in-a-split) {#can-i-change-the-percentages-in-a-split} +Generally, Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +#### How do Obol Splits work?[​](frequently-asked-questions.mdx#how-do-obol-splits-work) {#how-do-obol-splits-work} +You can read more about how Obol Splits work [here](obol-splits.md). + +#### Are Obol Splits open source?[​](frequently-asked-questions.mdx#are-obol-splits-open-source) {#are-obol-splits-open-source} +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +#### Are Obol Splits audited?[​](frequently-asked-questions.mdx#are-obol-splits-audited) {#are-obol-splits-audited} +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md). + +#### Are the Obol Splits contracts verified on Etherscan?[​](frequently-asked-questions.mdx#are-the-obol-splits-contracts-verified-on-etherscan) {#are-the-obol-splits-contracts-verified-on-etherscan} +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +#### Does my cold wallet have to call the Obol Splits contracts?[​](frequently-asked-questions.mdx#does-my-cold-wallet-have-to-call-the-obol-splits-contracts) {#does-my-cold-wallet-have-to-call-the-obol-splits-contracts} +No. Any address can trigger the contracts to move the funds, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +#### Are there any edge cases I should be aware of when using Obol Splits?[​](frequently-asked-questions.mdx#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits) {#are-there-any-edge-cases-i-should-be-aware-of-when-using-obol-splits} +The most important decision is to be aware of whether or not the Split contract you are using has been set up with editability. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is not to have an editable splitter, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](obol-splits.md#optimistic-withdrawal-recipient), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. + +### Debugging Errors in Logs[​](frequently-asked-questions.mdx#debugging-errors-in-logs) {#debugging-errors-in-logs} +You can check if the containers on your node are outputting errors by running `docker compose logs` on a machine with a running cluster. + +Diagnose some common errors and view their resolutions [here](../../advanced-and-troubleshooting/troubleshooting/errors.md). diff --git a/versioned_docs/version-v1.9/learn/intro/key-concepts.md b/versioned_docs/version-v1.9/learn/intro/key-concepts.md new file mode 100644 index 0000000000..7cba02c51b --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/key-concepts.md @@ -0,0 +1,117 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Key Staking Concepts" +slug: /learn/readme/key-concepts +--- + +# Key Staking Concepts + +This page outlines a number of the key concepts behind the various technologies that Obol is developing. + +## Distributed validator + +![](/img/gitbook/image-16-1.png) + +A distributed validator is an Ethereum proof-of-stake validator that runs on more than one node/machine. This functionality is possible with the use of **Distributed Validator Technology** (DVT). + +Distributed validator technology removes some of the single points of failure in validation. Should <33% of the participating nodes in a DV cluster go offline, the remaining active nodes can still come to consensus on what to sign and can produce valid signatures for their staking duties. This is known as Active/Active redundancy, a common pattern for minimising downtime in mission-critical systems. + +## Distributed Validator Node + +![](/img/gitbook/image-1-1-1-1.png) + +A distributed validator node is the set of clients an operator needs to configure and run to fulfil the duties of a Distributed Validator Operator. An operator may also run redundant execution and consensus clients, an execution payload relayer like [mev-boost](https://github.com/flashbots/mev-boost), or other monitoring or telemetry services on the same hardware to ensure optimal performance. + +In the above example, the stack includes Geth, Lighthouse, Charon and Teku. + +### Execution Client + +![](/img/gitbook/image-2-1-1.png) + +An execution client (formerly known as an Eth1 client) specialises in running the EVM and managing the transaction pool for the Ethereum network. These clients provide execution payloads to consensus clients for inclusion into blocks. + +Examples of execution clients include: + +* [Go-Ethereum](https://geth.ethereum.org/) +* [Nethermind](https://docs.nethermind.io/) +* [Erigon](https://github.com/ledgerwatch/erigon) + +### Consensus Client + +![](/img/gitbook/image-3-1-1.png) + +A consensus client's duty is to run the proof-of-stake consensus layer of Ethereum, often referred to as the beacon chain. + +Examples of Consensus clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/beacon-node) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-bn.html) +* [Nimbus](https://nimbus.guide/) +* [Lodestar](https://github.com/ChainSafe/lodestar) + +### Distributed Validator Client + +![](/img/gitbook/image-4-1-1.png) + +A distributed validator client intercepts the validator client ↔ consensus client communication flow over the [standardised REST API](https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi), and focuses on two core duties: + +* Coming to consensus on a candidate duty for all validators to sign. +* Combining signatures from all validators into a distributed validator signature. + +The only example of a distributed validator client built with a non-custodial middleware architecture to date is [Charon](../charon/intro/). + +### Validator Client + +![](/img/gitbook/image-5-1-1.png) + +A validator client is a piece of code that operates one or more Ethereum validators. + +Examples of validator clients include: + +* [Prysm](https://docs.prylabs.network/docs/how-prysm-works/prysm-validator-client/) +* [Lodestar](https://github.com/ChainSafe/lodestar) +* [Teku](https://docs.teku.consensys.net/en/stable/) +* [Lighthouse](https://lighthouse-book.sigmaprime.io/api-vc.html) +* [Vouch](https://www.attestant.io/posts/introducing-vouch/) + +## Distributed Validator Cluster + +![](/img/gitbook/image-6-1-1.png) + +A distributed validator cluster is a collection of distributed validator nodes connected together to service a set of distributed validators generated during a DVK ceremony. + +### Distributed Validator Key + +![](/img/gitbook/image-7-1-1.png) + +A distributed validator key is a group of BLS private keys which together operate as a threshold key for participating in proof-of-stake consensus. + +### Distributed Validator Key Share + +One piece of the distributed validator private key. + +### Distributed Validator Threshold + +The number of nodes in a cluster that need to be online and honest for their distributed validators to be online is outlined in the following table. + +| Cluster Size | Threshold | Note | +| :----------: | :-------: | --------------------------------------------- | +| 3 | 2/3 | Minimum to tolerate one offline node | +| 4 | 3/4 | Minimum to tolerate one **malicious** node | +| 5 | 4/5 | | +| 6 | 4/6 | Minimum to tolerate two offline nodes | +| 7 | 5/7 | Minimum to tolerate two **malicious** nodes | +| 8 | 6/8 | | +| 9 | 6/9 | Minimum to tolerate three offline nodes | +| 10 | 7/10 | Minimum to tolerate three **malicious** nodes | + +:::warning +Running the same Charon node in two places is considered a malicious (or byzantine) act, you should **take extra care not to run duplicate instances of a particular Charon peer if it is running in a three node setup**, which only tolerates one offline node, not a malicious one. Read more [here](../charon/cluster-configuration/#cluster-size-and-resilience). +::: + +### Distributed Validator Key Generation Ceremony + +To achieve fault tolerance in a distributed validator, the individual private key shares need to be generated together. Rather than have a trusted dealer produce a private key, split it and distribute it, the preferred approach is to never construct the full private key at any point, by having each operator in the distributed validator cluster participate in what is known as a Distributed Key Generation ceremony. + +A distributed validator key generation ceremony is a type of DKG ceremony. A ceremony produces signed validator deposit and exit data, along with all of the validator key shares and their associated metadata. Read more about these ceremonies [here](../charon/dkg/). diff --git a/versioned_docs/version-v1.9/learn/intro/launchpad.md b/versioned_docs/version-v1.9/learn/intro/launchpad.md new file mode 100644 index 0000000000..61bed058a1 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/launchpad.md @@ -0,0 +1,51 @@ +--- +description: "A dapp to securely create Distributed Validators alone or with a group." +sidebar_label: "DV Launchpad" +slug: /learn/readme/launchpad +--- + +# DV Launchpad + +In order to activate an Ethereum validator, 32 ETH must be deposited into the official deposit contract. Distributed validators are no different. + +The vast majority of users that created validators to date have used the [~~**Eth2**~~\*\* Staking Launchpad\*\*](https://launchpad.ethereum.org/), a public good open-source website built by the Ethereum Foundation alongside participants who later went on to found Obol. This tool has been wildly successful in the safe and educational creation of a significant number of validators on the Ethereum mainnet. + +To facilitate the generation of distributed validator keys amongst remote users with high-trust, the Obol Network developed and maintains a website that enables a group of users to come together and create these threshold keys: **The DV Launchpad**. + +![](/img/gitbook/image-16-1-1.png) + +## Getting started + +For more information on running Charon in a UI-friendly way through the DV Launchpad, take a look at our [Quickstart Guides](../../run-a-dv/start/quickstart_overview.md). + +## DV Launchpad Links + +| Ethereum Network | Launchpad | +| ---------------- | -------------------------------------- | +| Mainnet | https://launchpad.obol.org | +| Gnosis Chain | https://gnosischain.launchpad.obol.org | +| Hoodi | https://hoodi.launchpad.obol.org | +| Holesky | https://holesky.launchpad.obol.org | +| Sepolia | https://sepolia.launchpad.obol.org | + +## Operator Dashboard + +Clicking on "dashboard" on the top-right of the launchpad brings you to the operator view, where you can view information about the DV operator corresponding to the wallet address currently connected to the launchpad. It is also possible to view information about another operator, by substituting another wallet address in the URL, or using the explorer, described below. + +![](/img/gitbook/image-17-1.png) + +## View a Cluster + +An operator can be part of multiple clusters. Clusters, and cluster invites, are shown on the operator page. Clicking on a cluster takes you to the cluster page. Here you can see the status of the cluster, the operators, and validators associated with the cluster. + +![](/img/gitbook/image-18-1.png) + +> \[!TIP] If you created a cluster locally, and didn't use the `--publish` command at the time, you can manually publish it by running this command from the folder with the `cluster-lock.json` in it. +> +> `curl -X POST -H "Content-Type: application/json" -d @cluster-lock.json https://api.obol.tech/v1/lock` + +## Use the Explorer + +Clicking "explore" on the top-right of the launchpad brings you to the explorer view. It shows information about every DV cluster and operator being tracked by Obol. You can search for a cluster or operator by name, or filter based on badge or protocol type. + +![](/img/gitbook/image-19-1.png) diff --git a/versioned_docs/version-v1.9/learn/intro/obol-collective.md b/versioned_docs/version-v1.9/learn/intro/obol-collective.md new file mode 100644 index 0000000000..c4d97bcbf8 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/obol-collective.md @@ -0,0 +1,32 @@ +--- +description: "The Obol Collective" +sidebar_label: "Obol Collective" +slug: /learn/readme/obol-collective +--- + +# Obol Collective + +## What is the Obol Collective? + +Obol is the largest Decentralised Operator Ecosystem. We provide the technology, opportunities, and community to scale decentralised infrastructure networks. The list of Obol Collective participants includes 50+ staking protocols, client teams, software tools, education & community projects, professional node operators, home operators, and stakers, including names like EigenLayer, Lido, EtherFi, Figment, Bitcoin Suisse, Stakewise, Nethermind, Blockdaemon, Chorus One, DappNode, and many more. Learn more at [Obol.org](https://obol.org). + +![](/img/gitbook/DecentralizedOperatorEcosystem.png) + +## Scaling Infrastructure Networks + +Obol is focused on scaling consensus by providing permissionless access to Distributed Validators (DVs), which offer not only protection against client issues and key mismanagement, but also Byzantine fault tolerance. We believe that distributed validators should and will make up a large portion of mainnet validator configurations, with the transition of the Ethereum community to DVs enabling a new trust paradigm. + +The Distributed Validator middleware client, Charon, boosts the security, resilience, and decentralisation of the Ethereum validator network by enabling “squad staking”. The Collective is fueled by Obol’s economic model, which directs funding to ecosystem projects via retroactive funding - a positive flywheel to accelerate adoption of DVs and scale infrastructure networks like Ethereum. + +## What is DV Labs?​ + +DV Labs (originally “Obol Labs”) is one of the core research and software development teams building DVT. DV Labs’ mission is to build shared web3 technologies for node operators, to establish a credibly neutral and trust-minimised infrastructure layer. DV Labs’ Distributed Validator middleware client, Charon, boosts security, resilience, and decentralisation by enabling “squad staking”. Learn more at [DVLabs.tech](https://dvlabs.tech). + +### The Obol Product Suite + +The [Obol Product Suite](https://obol.org/product-suite) empowers any node operator to run fault-tolerant, slashing-resistant distributed validators. Choose from [a suite of tools](../further-reading/resources.md) to get distributed validators running on any type of hardware, with any combination of software clients. + +* Foundation: [Charon](../charon/intro.md), a middleware client that enables validators to run in a fault-tolerant, distributed manner; +* Configuration: The [Distributed Validator Launchpad](launchpad.md), a user interface for configuring Distributed Validators. The Obol [SDK](../../sdk/index.md) & [API](../../api/what-is-this-api.md), allowing Distributed Validator clusters to be configured and run at scale, for example within staking protocols. +* Launchers: Obol's [Charon Distributed Validator Node (CDVN)](../../run-a-dv/start/create-a-dv-with-a-group.mdx), Obol's Distributed Validator Pod. +* Rewards: [Obol Splits](obol-splits.md), a set of solidity smart contracts for the distribution of rewards from Distributed Validators, amongst multiple node operations. diff --git a/versioned_docs/version-v1.9/learn/intro/obol-incentives.md b/versioned_docs/version-v1.9/learn/intro/obol-incentives.md new file mode 100644 index 0000000000..29cbdb5a93 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/obol-incentives.md @@ -0,0 +1,178 @@ +--- +sidebar_label: "OBOL Incentives" +slug: /learn/readme/obol-incentives +--- + +# OBOL Incentives + +## OBOL Incentives Program + +The **OBOL Incentives Program** is designed to be powerful and transparent, rewarding anyone OBOL tokens for staking on **Distributed Validators (DVs).** + +### What is the OBOL Incentives Program? + +OBOL Incentives offer an opportunity to **earn OBOL Token incentives** for staking on **Distributed Validators**. + +* **12.5 million OBOL Tokens** (2.5% of the total supply) will be distributed in the **first year (2025).** +* Incentives **begin accruing on March 24th, 2025.** +* **Claiming** will be possible shortly after the OBOL Token is unlocked (as per O[IP#2](https://community.obol.org/t/oip-2-unlock-obol-token/)) and starts trading. + +Each week, **1/52 of the 12.5M OBOL** will be distributed (**\~240,385 OBOL per week**). + +If you are staking with a partner, incentives will either be claimed via the participating partner UI frontends or via the [DV Launchpad](https://launchpad.obol.org/) as per the table below. + +*** + +### How do I participate? + +You can participate by: + +1. **Staking through Staking Partners** + * For the latest list of partners that qualify for OBOL Incentives, visit [https://obol.org/incentives](https://obol.org/incentives) and see the table below. +2. **Running Your Own DV Cluster** + * Use the [DV Launchpad](https://launchpad.obol.org) to create and manage your own DV cluster, e.g., using a [DappNode](https://dappnode.com/) or other hardware. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. + * This method directly supports Ethereum’s decentralization while earning OBOL incentives. + * Visit the official Obol Discord to find squad mates. + +*** + +### Is existing stake eligible? + +* If you are staking yourself directly on Obol DVs and/or Squad Staking, your stake is 100% eligible for rewards. Please note, you must opt into [1% for Decentralization](https://blog.obol.org/1-percent-for-decentralisation/) to qualify for Obol Incentives. +* If you are staking with a partner protocol, it's best to review the details of that partner at Obol.org/incentives. Only ETH staked on Obol DVs with qualified partners qualify for Obol Incentives and not all partners are created equal. + +*** + +### How much OBOL will I receive per ETH staked on DVs? + +* **The OBOL amount per ETH depends on total ETH participation.** +* The **240,385 OBOL per week** is distributed **proportionally** across all participating ETH. +* Your **share of the total ETH** determines your **share of OBOL incentives.** +* If you need help calculating your potential rewards, feel free to use this community created calculator: + * **NOTE:** This is a community created calculator, is not managed by DV Labs or the Obol Association, and is not to be fully trusted. + +*** + +### How are incentives tracked? + +OBOL incentives are based on staking rewards earned by validators (pubkeys). Performance factors like effectiveness and uptime impact rewards. + +* Incentives are tracked off-chain in a centralized database. +* API endpoints allow users & protocols to query earned incentives. +* Incentives are displayed in the [Obol DV Launchpad](https://launchpad.obol.org) and/or participating partner UI frontends. + +*** + +### How do you ensure calculations for OBOL Incentives are made properly? + +Our rewards calculation and distribution system is built for accuracy, transparency, and security. We use Miga Labs' indexer to reliably track validator rewards, and all critical data—such as total rewards, split configurations, and depositor allocations—is verified on-chain and made publicly available for cross-verification. In cases where a partner misreports depositor splits, it only affects their own internal distribution and does not compromise the total rewards allocation or the fairness of the system. + +*** + +### How can I track my OBOL incentives? + +* For those staking with a Partner: Your staking platform should show and distribute your OBOL incentives in their UI frontend. +* For those running their own Distributed Validators: Incentives are displayed on the [DV Launchpad](https://launchpad.obol.org). + +*** + +### What benefits do I get from the OBOL Token? + +OBOL Tokens serve as the basis for ownership and governance of the Obol Collective.\ +Learn more on the OBOL Token page. + +![](/img/gitbook/image-57.png) + +*** + +### How are incentives calculated? + +OBOL incentives are tied to validator staking rewards and calculated daily. + +For a validator with total staking rewards ( R ), and operator split percentages ( p\_1, p\_2, ..., p\_n ), the operator’s rewards (Oᵢ) are: + +\[ Oᵢ = R × pᵢ × 0.01 × 1.01 ] + +* ( pᵢ ) = Operator’s percentage split. +* The 1.01 multiplier ensures the full 1% of rewards is distributed correctly. + +Higher effectiveness & uptime = more incentives. + +*** + +### Can I withdraw my staked ETH at any time? + +Yes, you can withdraw at any time but you **stop accruing incentives** upon withdrawal. + +* If you are staking with a partner, they may choose to set penalties for early withdrawals but this is not common. +* If you are running your own distributed validator, there is no penalty for withdrawing or exiting. + +*** + +### What is the minimum amount of ETH needed to stake? + +* If you are staking with a partner, they will have their own minimum deposit amount. +* If you are running your own distributed validator, the total amount required by your squad is 32 ETH. +* Check each partner’s requirements at [https://obol.org/incentives](https://obol.org/incentives). + +*** + +### What happens if my validator has downtime? + +Since OBOL incentives are tied to staking rewards, validator performance metrics directly impact earned incentives. + +* More uptime & effectiveness = More incentives. +* Longer downtime = Fewer rewards. + +*** + +### Will my incentives be public? + +Yes. Incentives are publicly accessible through the Obol API (with the correct protocol address). + +*** + +### How do I increase the amount of OBOL I can earn? + +* Increase the amount of ETH staked. +* Improve validator performance (higher uptime & effectiveness). + +*** + +### What are the benefits of using Distributed Validators? + +Distributed Validators improve performance, lower risks and increase rewards. Learn more at [obol.org/learn](https://obol.org/learn). + +*** + +### How can I get support if I have issues? + +* Join the Obol Discord community: [discord.obol.org](https://discord.obol.org). +* If you are staking with a partner, reach out to them directly. + +*** + +### Who are the staking partners and how can I get access to my rewards? + +For each partner listed below, you’ll find: + +* The eligible TVL for Obol Incentives +* How depositors can claim these incentives +* The portion of incentives (if any) retained by the partner + +You’ll also see an estimated multiplier, which reflects how each partner manages these incentives. + +* A **multiplier below 100%** typically means Obol incentives are spread across all depositors, even though only a portion of the partner's total TVL is running Obol DVs. +* A **multiplier above 100%** usually indicates that the partner is concentrating Obol rewards on a specific vault, which has less TVL than the total TVL running Obol DVs. + +| Partner Name | Eligible TVL | Claim Method | Incentives Split | Multiplier | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | +| [Mellow DVV](https://app.mellow.finance/vaults/ethereum-dvsteth) |

All of Mellow DVV TVL
+ Lido SDVT Module validators added post Jan 13th Airdrop
+ Lido CSM TVL ran by Obol DVs

| [Obol Launchpad](https://launchpad.obol.org/) |
  • Mellow Depositors: 80% for CSM TVL, 90% for SDVT TVL
  • Rest to Node Operators
| ≥ 100% | +| [Ether.fi](https://app.ether.fi/weeth) | Portion of total TVL running on Obol DVs | Directly accruing as [KING rewards](https://etherfi.gitbook.io/etherfi/king-protocol-formerly-lrt) | According to partner's [fee structure](https://etherfi.gitbook.io/etherfi/ether.fi-whitepaper/ether.fi-staking) | <100% | +| Blockdaemon | TBD | [Blockdaemon UI](https://www.blockdaemon.com/) | According to partner's fee structure | TBD | +| [Chorus One](https://opus.chorus.one/pool/stake/) | Total TVL of the OBOL Vault | TBD | According to partner's fee structure | = 100% | +| [Dinero](https://dinero.xyz/pxeth/deposit) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Stakewise](https://app.stakewise.io/) | Portion of total TVL running on Obol DVs | [Stakewise UI](https://app.stakewise.io/) | According to partner's [fee structure](https://docs.stakewise.io/protocol-overview-in-depth/fees#vault-staking-fee) | < 100% | +| [Swell](https://app.swellnetwork.io/stake/rsweth) | Portion of total TVL running on Obol DVs | TBD | According to partner's fee structure | < 100% | +| [Hashkey Cloud](https://www.hashkey.cloud/) | TBD | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | TBD | +| [Validation Cloud](https://www.validationcloud.io/) | Portion of total TVL running on Obol DVs | [Obol Launchpad](https://launchpad.obol.org/) | According to partner's fee structure | = 100% | diff --git a/versioned_docs/version-v1.9/learn/intro/obol-splits.md b/versioned_docs/version-v1.9/learn/intro/obol-splits.md new file mode 100644 index 0000000000..c63a181ceb --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/obol-splits.md @@ -0,0 +1,255 @@ +--- +sidebar_label: "Obol Splits" +slug: /learn/readme/obol-splits +--- + +# Obol Splits + +Obol develops and maintains a suite of smart contracts for use with Distributed Validators and their surrounding ecosystem of decentralised infrastructure. These contracts include: + +* Validator Managers: Contracts used for a validator's withdrawal address, enabling ownership transfer, partial withdrawals, full exits, and operator rotation. +* Reward Splitting contracts: Contracts to split ether (and tokens) across multiple entities. Developed by [Splits.org](https://splits.org/) + +Key Design Principles the Obol Smart Contract suite include are: + +* That they are secure. All [released](https://github.com/ObolNetwork/obol-splits/releases/) Obol Splits products are [audited by high quality security teams](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments). +* They are not upgradeable. +* They are self-sovereign. Any permissioned actions, such as withdrawal, exit, or operator rotation, are controlled by the user, not an unaccountable set of third parties with the ability to upgrade your contract's behaviour. +* They do not require a token to function. +* They are oracle-free. (Unless you intend to leverage a [swapper](https://docs.splits.org/core/swapper)). +* They divide the reward ether from principal ether such that staking providers can be paid a percentage of the _reward_ they accrue for the principal provider rather than a percentage of _principal and reward_. +* That rewards can be withdrawn in an ongoing manner without exiting the validator. (Some conditions apply). + +## Obol Validator Managers[​](obol-splits.md#obol-validator-managers) + +An Obol Validator Manager (OVM) is a smart contract which manages the deposit, withdrawal, exit, and public key rotation of one or more Ethereum validators. It is deployed as the withdrawal address for a validator and supports 0x01 and 0x02 validator types. + +### Creation + +You create a new Validator Manager contract using the [factory](obol-splits.md#ovm-factory-deployment) by calling the `ObolValidatorManagerFactory.createObolValidatorManager()` function, passing: + +* `owner` - The address that is the ultimate administrator of this Validator Manager deployment, it manages the assignment of roles for the contract, and **can call all privileged methods**. This address is best suited to being a multi-sig (such as a [SAFE](https://safe.global)) with a large number of signers, used only as a fallback, or it can be owned temporarily, fine-grained roles can be assigned to addresses, and then the [`renounceOwnership()`](https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol#L186) or [`transferOwnership()`](https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol#L174) methods can be called. +* `beneficiary` - This is the **address where the principal will be returned** to when validators exit or a withdrawal above the `principalThreshold` is made. This can be changed later by the `owner` or addresses with the `SET_BENEFICIARY_ROLE`. +* `rewardRecipient` - This is the **address where the accrued ether reward will be sent** when `distributeFunds()` is called. Usually it is a [Pull Split](https://docs.splits.org/core/split-v2#how-it-works) from [splits.org](https://splits.org). This can be changed later by the `owner` or addresses with the `SET_REWARD_ROLE`. +* `principalThreshold` - This is a configurable amount of Ether which dictates at what amount of value in the contract should we consider it to be principal being returned rather than reward accrued. The amount is immutable. A sensible default here is 16 ether (16000000000 gwei), the threshold used in Obol's earlier [Optimistic Withdrawal Recipients](obol-splits.md#optimistic-withdrawal-recipient). Further detail in the [FAQ](obol-splits.md#faq) section. + +### Roles + +Obol Validator Managers implement standard Role-Based Access Control. The OVM has the following roles that can be granted by the OVM owner, using the `grantRoles()` function. + +* `DEPOSIT_ROLE`: Permits an address to call the `deposit()` function. +* `CONSOLIDATION_ROLE`: Permits an address to initiate a consolidation between one or more source validators and a target validator, all managed by this contract. All source and target validators must be active with a balance greater than 32 ether. +* `WITHDRAWAL_ROLE`: Permits an address to trigger a partial withdrawal, or full exit of all validators managed by this contract using [EIP7002](https://eips.ethereum.org/EIPS/eip-7002). +* `SET_BENEFICIARY_ROLE`: Permits an address to change the recipient of the principal returned when validators exit, or a withdrawal above the principalThreshold is initiated. Also this permits an address to adjust the amount of principal stake being tracked by the contract. +* `SET_REWARD_ROLE`: Permits an address to change the recipient of the reward when `distributeFunds()` is called. +* `RECOVER_FUNDS_ROLE`: Permits an address to initiate `ERC20.transfer()` calls to arbitrary external addresses, with the intent to recover otherwise stuck tokens. + +### Deposit + +Every validator managed by an Obol Validator Manager must be deposited through the `deposit()` method. This method has the same signature as the official Ethereum deposit contract, but internally it accounts for the principal amount being deposited for the future calculation of returns of principal vs rewards. Only the `owner` address, or any address with the `DEPOSIT_ROLE` can call this method. + +:::info +If a deposit was done directly to the official Ethereum deposit contract, the OVM will not have recorded the principal amount. To fix this, consider using `setAmountOfPrincipalStake()` to update the total principal amount of stake. +::: + +### Partial Withdrawals & Full Exits + +Obol Validator Managers support [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) smart contract-based withdrawals. The `owner` address, or any address with the `WITHDRAWAL_ROLE` can call the `withdraw()` method to initiate a partial (or full) withdrawal of the balance of a validator managed by this contract. + +:::info +If you request to withdraw an amount that would leave a validator with less than a 32 ETH balance, only the amount that would leave the validator with 32 ETH will be withdrawn. +::: + +:::info +If you request to partially withdraw a validator's balance, the funds will be available in the OVM contract at the end of the exit queue. (Usually \~27 hours) + +However, if you withdraw the full balance of the validator, triggering its complete exit, the Ether will be available to the OVM contract once the validator is through the exit queue, **and** the skimming process has completed. (Average of \~5 days) This could add a number of days to the wait for validator funds, and full exiting at an optimal moment could significantly shorten the duration. +::: + +```solidity +function withdraw( + bytes[] calldata pubKeys, + uint64[] calldata amounts, + uint256 maxFeePerWithdrawal, + address excessFeeRecipient + ) external payable onlyOwnerOrRoles(WITHDRAWAL_ROLE) {} +``` + +```solidity title="Event" + /// Emitted when a withdrawal request is submitted for a validator + /// @param pubKey Validator public key + /// @param amount Withdrawal amount in gwei + /// @param fee Fee paid for the withdrawal + event WithdrawalRequested(bytes pubKey, uint64 indexed amount, uint256 indexed fee); +``` + +### Validator Consolidations + +Obol Validator Managers support [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) smart contract-based validator consolidations. This is an important feature for rotating the private keys for the validators managed by this contract. The rotation of private keys allows for the secure re-distribution of validation duties amongst new operators, without a significant period of inactivity in a normal exit and recreate flow. + +The `owner` address, or any address with the `CONSOLIDATION_ROLE` can call the `consolidate()` method, to initiate a consolidation between one or more source validators and a target validator, all managed by this contract. + +:::info +All source and target validators must be active with a balance greater than 32 ether for the consolidation to succeed. The target validator must be an 0x02 type validator, 0x01 type validators can become 0x02 type through a self-consolidation, where the public key is the `source` and `target`. +::: + +:::info +It is possible to permissionlessly consolidate a validator into (or out of) an OVM. This could result in the OVM's `amountOfPrincipalStake()` not accurately reflecting the true amount of stake on validators exiting to the OVM withdrawal address. This could result in more (or less) ether being treated as reward, and disbursed to the rewardRecipient address. The owner of the OVM or any address with the `SET_BENEFICIARY_ROLE` can update the amount of Ether treated as principal with the `setAmountOfPrincipalStake()` function. +::: + +```solidity + struct ConsolidationRequest { + bytes[] srcPubKeys; + bytes targetPubKey; + } + + function consolidate( + ConsolidationRequest[] calldata requests, + uint256 maxFeePerConsolidation, + address excessFeeRecipient + ) external payable onlyOwnerOrRoles(CONSOLIDATION_ROLE) {} +``` + +```solidity title="Event" + /// Emitted when a consolidation request is submitted + /// @param srcPubKey Source validator public key + /// @param targetPubKey Target validator public key + /// @param fee Fee paid for the consolidation + event ConsolidationRequested(bytes srcPubKey, bytes targetPubKey, uint256 indexed fee); +``` + +### Token Recovery + +The `owner` address, or any address with the `RECOVER_FUNDS_ROLE` can call the `recoverFunds()` method, to send an ERC20 token balance on the ObolValidatorManager contract to an arbitrary `recipient` address. + +:::warning +Be cautious when interacting with unknown ERC20 addresses, they may not behave as anticipated. +::: + +```solidity + /// Recover non-OVM tokens to a recipient + /// @param nonOVMToken Token to recover + /// @param recipient Address to receive recovered token + function recoverFunds(address nonOVMToken, address recipient) external onlyOwnerOrRoles(RECOVER_FUNDS_ROLE) {} +``` + +``` title="Event" + /// Emitted after tokens are recovered to a recipient + /// @param nonOVMToken Recovered token (cannot be ETH) + /// @param recipient Address receiving recovered token + /// @param amount Amount of recovered token + event RecoverNonOVMFunds(address indexed nonOVMToken, address indexed recipient, uint256 amount); +``` + +## Optimistic Withdrawal Recipient[​](obol-splits.md#optimistic-withdrawal-recipient) {#optimistic-withdrawal-recipient} +![](/img/gitbook/image-15-1-1.png) + +Optimistic Withdrawal Recipients (OWRs) **are the predecessor to Obol Validator Managers**. The primary addition with Validator Managers is the role-based control over validator withdrawals, exits and consolidations. + +Optimistic Withdrawal Recipients allow for the separation of reward from principal, as well as permitting the ongoing withdrawal of accruing rewards. + +An Optimistic Withdrawal Recipient [contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipient.sol) takes three inputs when deployed: + +* A _principal_ address: The address that controls where the principal ether will be transferred post-exit. +* A _reward_ address: The address where the accruing reward ether is transferred to. +* The amount of ether that makes up the principal. + +This contract **assumes that any ether that has appeared in its address since it was last able to do balance accounting is skimming reward from an ongoing validator** (or number of validators) unless the change is > 16 ether. This means balance skimming is immediately claimable as reward, while an inflow of e.g. 31 ether is tracked as a return of principal (despite being slashed in this example). + +:::danger +Worst-case mass slashings can theoretically exceed 16 ether, if this were to occur, the returned principal would be misclassified as a reward, and distributed to the wrong address. This risk is the drawback that makes this contract variant 'optimistic'. If you intend to use this contract type, **it is important you fully understand and accept this risk**. + +The alternative is to use a splits.org [waterfall contract](https://docs.splits.org/core/waterfall), which won't allow the claiming of rewards until all principal ether has been returned, meaning validators need to be exited for operators to claim their CL rewards. +::: + +This contract fits both design goals and can be used with thousands of validators. It is safe to deploy an Optimistic Withdrawal Recipient with a principal higher than you actually end up using, though you should process the accrued rewards before exiting a validator or the reward recipients will be short-changed as that balance may be counted as principal instead of reward the next time the contract is updated. If you activate more validators than you specified in your contract deployment, you will record too much ether as reward and will overpay your reward address with ether that was principal ether, not earned ether. Current iterations of this contract are not designed for editing the amount of principal set. + +## Split Contracts[​](obol-splits.md#split-contracts) {#split-contracts} +Validators have two streams of revenue, the consensus layer rewards and the execution layer rewards. Validator Managers focus on the former, split contracts focus on the latter. They are best used in tandem. + +![Obol Validator Manager in Tandem with an Execution Layer Fee recipient splitter contract](/img/gitbook/ovm_splits_overview.png) + +A split, or splitter, is a set of contracts that can divide ether or an ERC20 across a number of addresses. Splits are often used in conjunction with withdrawal recipients. Execution Layer rewards for a DV are directed to a split address through the use of a `fee recipient` address. Splits can be either immutable, or mutable by way of an admin address capable of updating them. + +Further information about splits can be found on the splits.org team's [docs site](https://docs.splits.org/). The addresses of their deployments can be found [here](https://docs.splits.org/core/split#addresses). + +### Split Controllers[​](obol-splits.md#split-controllers) {#split-controllers} +Splits can be completely edited through the use of the `controller` address, however, total editability of a split is not always wanted. We recommend using a [SAFE wallet](https://safe.global) to manage the Split. + +#### (Gnosis) SAFE wallet[​](obol-splits.md#gnosis-safe-wallet) {#gnosis-safe-wallet} +A [SAFE](https://safe.global/) is a common method to administer an editable split. The most well-known deployment of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/3-smart-contract.html). The SAFE can arbitrarily update the split to any set of addresses with any valid set of percentages. + +## Deployments + +### Obol Validator Manager Factory Deployment {#ovm-factory-deployment} +The `ObolValidatorManager` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/ovm/ObolValidatorManagerFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x2c26B5A373294CaccBd3DE817D9B7C6aea7De584](https://etherscan.io/address/0x2c26B5A373294CaccBd3DE817D9B7C6aea7De584) | +| Hoodi | [0x5754C8665B7e7BF15E83fCdF6d9636684B782b12](https://hoodi.etherscan.io/address/0x5754C8665B7e7BF15E83fCdF6d9636684B782b12) | +| Sepolia | [0xF32F8B563d8369d40C45D5d667C2B26937F2A3d3](https://sepolia.etherscan.io/address/0xF32F8B563d8369d40C45D5d667C2B26937F2A3d3) | + +### Obol Lido Split Factory Deployment {#ols-factory-deployment} +The `ObolLidoSplit` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/lido/ObolLidoSplitFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | --------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0xa9d94139a310150ca1163b5e23f3e1dbb7d9e2a6](https://etherscan.io/address/0xa9d94139a310150ca1163b5e23f3e1dbb7d9e2a6) | +| Hoodi | [0xb633CD420aF83E8A5172e299104842b63dd97ab7](https://hoodi.etherscan.io/address/0xb633CD420aF83E8A5172e299104842b63dd97ab7) | +| Sepolia | | + +### OWR Factory Deployment {#owr-factory-deployment} +The `OptimisticWithdrawalRecipient` contract is deployed via a [factory contract](https://github.com/ObolNetwork/obol-splits/blob/main/src/owr/OptimisticWithdrawalRecipientFactory.sol). The factory is deployed at the following addresses on the following chains. + +| Chain | Address | +| ------- | ----------------------------------------------------------------------------------------------------------------------------- | +| Mainnet | [0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522](https://etherscan.io/address/0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522) | +| Sepolia | [0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a](https://sepolia.etherscan.io/address/0xca78f8fda7ec13ae246e4d4cd38b9ce25a12e64a) | +| Hoodi | [0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7](https://hoodi.etherscan.io/address/0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7) | + +## FAQ + +### What are Obol Splits? + +Obol Splits refers to a collection of composable smart contracts that enable the splitting of validator rewards and/or principal in a non-custodial, trust-minimised manner. Obol Splits contains integrations to enable DVs within Lido with Obol Lido Splits, and Native Staking with Obol Validator Managers. + +### Are Obol Splits non-custodial? + +Yes. Unless you were to decide to [deploy an editable splitter contract](obol-splits.md#can-i-change-the-percentages-in-a-split), Obol Splits are immutable, non-upgradeable, non-custodial, and oracle-free. Obol Validator Managers have owners and Role-Based Access Control, but these are self-sovereign and up to the deployer to set and manage. There is no third party with access to or control of your validators unless you grant them such access. + +### Obol Validator Managers + +#### What happens if I deposit to an OVM managed validator directly with the Ethereum deposit contract instead of through the dedicated OVM.deposit() method? + +In this case, the OVM contract will not have recorded the deposit as principal to be returned, so when the validator exits, it will be sent to the reward address. Consider editing the reward address to pay 100% to the principal recipient, exiting the validator, claiming the 'rewards', and editing the reward split back to normal, before depositing through the OVM for **a new validator private key** that exits to the same OVM contract. + +#### What is the principal threshold for? + +Determining if Ether returned from a validator is principal deposited or rewards accrued is difficult. Rather than introducing an off-chain proof system, or trusted oracle, Obol Splits adopt an assumption that a mass slashing so severe that the principal returned is less than 16 eth is very rare, and the outcome that would happen in that case is the rewards would be sent to the reward rather than principal address, an accepted risk. This however does impact reward claiming on very large 0x02 validators. A validator could have earned 20 ether in rewards, and if a request for withdrawal of 20 ether is processed, it would be subtracted from principal and disbursed to the principal recipient, and upon a full exit, the remaining eth beyond the principal would be sent to the rewards address. To avoid this, entities with the `WITHDRAWAL_ROLE` should withdraw increments less than the `principalThreshold` if they want it treated as reward, and more than `principalThreshold` if they want to process it as a direct exit. + +### Can I change the percentages in a split? + +Generally Obol Splits are deployed in an immutable fashion, meaning you cannot edit the percentages after deployment. However, if you were to choose to deploy a _controllable_ splitter contract when creating your Split, then yes, the address you select as controller can update the split percentages arbitrarily. A common pattern for this use case is to use a Gnosis SAFE as the controller address for the split, giving a group of entities (usually the operators and principal provider) the ability to update the percentages if need be. A well-known example of this pattern is the [Protocol Guild](https://protocol-guild.readthedocs.io/en/latest/03-onchain-architecture.html). + +### Are Obol Splits open source? + +Yes, Obol Splits are licensed under GPLv3 and the source code is available [here](https://github.com/ObolNetwork/obol-splits). + +### Are Obol Splits audited? + +The Obol Splits contracts have been audited, though further development has continued on the contracts since. Consult the audit results [here](../../advanced-and-troubleshooting/security/overview.md#list-of-security-audits-and-assessments) and always deploy contracts only from published [releases](https://github.com/ObolNetwork/obol-splits/releases). + +### Are the Obol Splits contracts verified on Etherscan? + +Yes, you can view the verified contracts on Etherscan. A list of the contract deployments can be found [here](https://github.com/ObolNetwork/obol-splits?#deployment). + +### Does my cold wallet have to call the Obol Splits contracts? + +No. Any address can trigger the contracts to distribute the withdrawn/skimmed ether, they do not need to be a member of the Split either. You can set your cold wallet/custodian address as the recipient of the principal and rewards, and use any hot wallet to pay the gas fees to push the ether into the recipient address. + +### Are there any edge cases I should be aware of when using Obol Splits? + +The most important thing to be aware of is what address is the owner of the Obol Validator Manager, whether it has assigned any other addresses any roles, and whether or not the Split contract you are using has been set up with editability and by which address. If a splitter is editable, you should understand what the address that can edit the split does. Is the editor an EOA? Who controls that address? How secure is their seed phrase? Is it a smart contract? What can that contract do? Can the controller contract be upgraded? etc. Generally, the safest thing in Obol's perspective is to use a high threshold multi-sign like a SAFE as the `owner`/`controller`, or to renounce ownership and control entirely, and if in the future you are unhappy with the configuration, that you exit the validator and create a fresh cluster with new settings that fit your needs. + +Another aspect to be aware of is how the splitting of principal from rewards works using the Optimistic Withdrawal Recipient contract. There are edge cases relating to not calling the contracts periodically or ahead of a withdrawal, activating more validators than the contract was configured for, and a worst-case mass slashing on the network. Consult the documentation on the contract [here](obol-splits.md#optimistic-withdrawal-recipient), its audit [here](../../advanced-and-troubleshooting/security/smart-contract-audit.md), and follow up with the core team if you have further questions. diff --git a/versioned_docs/version-v1.9/learn/intro/obol-vs-others.md b/versioned_docs/version-v1.9/learn/intro/obol-vs-others.md new file mode 100644 index 0000000000..53d4701ce2 --- /dev/null +++ b/versioned_docs/version-v1.9/learn/intro/obol-vs-others.md @@ -0,0 +1,51 @@ +--- +description: "Some of the key terms in the field of Distributed Validator Technology" +sidebar_label: "Obol vs Other DV Implementations" +slug: /learn/readme/obol-vs-others +--- + +# Obol vs Other DV Implementations + +This page outlines the unique features of Obol's DV implemenation, constrasting with other DV implementations. We built Obol’s DVT as a middleware to keep Ethereum secure, resilient, and composable. See also the blog article [Why We Built Charon as a Middleware](https://blog.obol.org/why-we-built-charon-as-a-middleware/). + +![](/img/gitbook/image-8-1-1.png) + +## No private keys put on chain + +Obol's distributed key generation (DKG) event generates key shares for each node within the DV cluster. The entire validator key NEVER exists in one place. Keys are generated locally on the nodes, and can be backed up. The private keys of Obol DVs are NEVER uploaded to the internet or published on-chain. + +An alternative approach to doing this is to split it into shares, encrypt each share with the public key of a node operator, and publish the encrypted private key on chain. The operators’ node key could then decrypt the validator private key. In our opinion, this is not secure. We believe that the safest approach is to avoid the existence of a singular private key, and certainly never to post any private key to a public blockchain network. + +## Cluster independance: Clusters can upgrade independently + +In an Obol DV cluster, nodes use LibP2P to communicate directly with each other, and communications are end-to-end encrypted with TLS. Clusters are independent from one another, can run different versions of Charon, and don't need to upgrade together. This means that when a new version of Obol’s Charon is released, Obol DV clusters can upgrade on their own time, individually from other DV clusters. Charon will NEVER require a hard fork or simultaneous updates across clusters for any upgrades. + +![](/img/gitbook/image-9-1-1.png) + +## Works with existing validator clients and keys + +We built Obol’s DV implementation as a secure and trust-minimised middleware architecture. Our middleware client, Charon, doesn’t replace anything in the client stack, instead it sits between the consensus and validator clients. Node operators integrating the Charon DVT middleware into their stack can continue to use the same clients and private key infrastructure as before, albeit with a different key generation method. + +The alternative approach to DV design is to replace the validator client with a DV-native client, which has custody of the private keys and the capability to sign arbitrary data. However, in our opinion a full validator client capable of signing and exfiltrating arbitrary data without the oversight of a second software implementation has much higher risk of causing correlated slashing. + +![](/img/gitbook/image-10-1-1.png) + +This gives the benefit of having both Charon and the existing validator client as failsafes, greatly reducing the odds of unintended slashing. Even in the worst case scenario where Charon is compromised by a supply chain attack or a remote code execution attack, or the Obol team become bad actors and push a malicious release, Charon cannot do a lot of damage as a middleware. If a compromised Charon client proposes a potential double vote or surround vote for a validator to sign, the validator client will check its anti-slashing database, see that it has already signed something conflicting, and simply refuse to return a signature. Charon could propose that a validator should sign an invalid block, but the chain would reject this and simply consider the proposal missed - a much better outcome than slashing. + +## No non-ETH token risk + +Obol makes no changes to Ethereum’s standard bonding and reward mechanism, and does not require nodes to post any bonds additional to the 32 ETH required for a validator. To pay out rewards to operators, splitter contracts like [Obol Splits](obol-splits.md) can be used to withdraw and share rewards on a continuous basis. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-11-1-1.png) + +The alternative approach is to create a token and require stakers to pay operators in that token. This would require stakers to keep a balance of the network token ready for fee paying, in order to continue using the staking service. This mechanism would be informed by oracles, which decide when to post rewards and punish operators. This alternative model has some drawbacks. Namely, the varying price of the network’s unique token will change relative to the price of ETH: operators are not able to determine their commission as a percentage of ETH staked, and stakers likewise must consider the additional initial cost of purchasing the token to determine their long-term rate of return on their staked ETH. + +![](/img/gitbook/image-12-1-1.png) + +## Non-custodial reward splits + +(see also the [docs page on Splits](obol-splits.md), and the [Splits.org blog article](https://splits.org/blog/obol-ethereum-resilience/).) + +To pay out rewards to operators, splitter contracts like Obol Splits can be used to withdraw and share rewards on a continuous basis. Two key goals of validator reward management are: 1. To be able to differentiate reward ether from principal ether such that node operators can be paid a percentage of the _reward_ they accrue for the principal provider, rather than a percentage of _principal and reward_. 2. To be able to withdraw the rewards in an ongoing manner without exiting the validator. This allows products like liquid staking protocols to be built on top of Obol, implementing a bond or unique token into their protocol, should they choose to do so. + +![](/img/gitbook/image-13-1-1.png) diff --git a/versioned_docs/version-v1.9/learn/introduction/learn-about-obol/README.md b/versioned_docs/version-v1.9/learn/introduction/learn-about-obol/README.md new file mode 100644 index 0000000000..cc14c2d1ec --- /dev/null +++ b/versioned_docs/version-v1.9/learn/introduction/learn-about-obol/README.md @@ -0,0 +1,25 @@ +--- +title: "Learn About Obol" +description: "Start here for the core concepts behind Obol and distributed validators" +sidebar_label: "Learn About Obol" +slug: /learn/readme/learn-about-obol +--- + +# Learn About Obol + +Obol is deeply embedded in Ethereum, working with node operators, staking protocols, and institutions to advance the staking ecosystem. + +The team and community come from the early Proof-of-Stake era, including contributors to the original Ethereum Staking Launchpad, and continue to focus on the important work that helps Ethereum scale while remaining decentralized. + +This section is a starting point for the core topics behind Obol and how it fits into Ethereum staking today. + +*** + + diff --git a/versioned_docs/version-v1.9/obol-stack/README.md b/versioned_docs/version-v1.9/obol-stack/README.md new file mode 100644 index 0000000000..0734aad742 --- /dev/null +++ b/versioned_docs/version-v1.9/obol-stack/README.md @@ -0,0 +1,112 @@ +--- +description: "A framework for AI agents to run decentralised infrastructure locally" +sidebar_label: "Introduction" +slug: /obol-stack/obol-stack +--- + +# Introduction + +The Obol Stack is a local development environment for running AI agents alongside blockchain infrastructure. It provides a simplified CLI for managing a Kubernetes cluster with an AI agent ([OpenClaw](https://openclaw.ai)), dynamically deployable blockchain networks, and public access via Cloudflare tunnels. + +:::info +The Obol Stack is alpha software. For production deployments, refer to the respective network documentation and use appropriate infrastructure. +::: + +## What is the Obol Stack? + +Obol Stack is a two-part system: + +1. **obolup.sh** - A bootstrap installer that sets up your environment +2. **obol CLI** - A Go-based binary for stack, agent, and network management + +The stack runs entirely on your local machine using [k3d](https://k3d.io/) (Kubernetes in Docker), providing a lightweight yet fully-featured Kubernetes environment. + +## Key features + +* **Agent-first** - Deploy an AI agent (OpenClaw) that can interact with blockchain networks and expose services. +* **Multiple network support** - Deploy Ethereum nodes, Aztec sequencers, and more. +* **Unique deployments** - Each installation creates a uniquely-namespaced deployment, allowing multiple instances to run simultaneously. +* **Public access** - Expose services to the internet via Cloudflare tunnels and x402 payment gateways. +* **Simplified tooling** - Wraps kubectl, helm, and other Kubernetes tools with automatic configuration. + +## CLI overview + +| Command | Description | +| --------------------------------------------- | ------------------------------ | +| `obol stack init / up / down / purge` | Cluster lifecycle management | +| `obol agent init` | Set up the AI agent (OpenClaw) | +| `obol openclaw dashboard / setup / ...` | Manage OpenClaw instances | +| `obol model setup / status` | Configure LLM providers | +| `obol network list / install / sync / delete` | Manage blockchain networks | +| `obol app install / sync / list / delete` | Install arbitrary Helm charts | +| `obol tunnel status / login / provision` | Manage Cloudflare tunnels | +| `obol kubectl / helm / k9s` | Kubernetes tool passthroughs | + +## Default infrastructure + +When you start the stack, the following services are deployed automatically: + +| Service | Namespace | Description | +| ----------------- | --------------- | ------------------------------------------------ | +| **Traefik** | `traefik` | Gateway API ingress controller | +| **Cloudflared** | `traefik` | Cloudflare tunnel connector | +| **ERPC** | `erpc` | Unified RPC load balancer for Ethereum endpoints | +| **Obol Frontend** | `obol-frontend` | Web management dashboard | +| **Monitoring** | `monitoring` | Prometheus + kube-prometheus-stack | +| **llmspy** | `llm` | LLM proxy/router for AI agent traffic | + +## System requirements + +### Prerequisites + +* **Docker** 20.10.0 or later (daemon must be running) +* **macOS** (Darwin) or **Linux** +* **amd64** or **arm64** architecture + +### Resource recommendations + +| Component | Minimum | Recommended | +| ----------- | ------- | --------------------------- | +| **CPU** | 4 cores | 8 cores | +| **RAM** | 8 GB | 16 GB | +| **Storage** | 50 GB | 500+ GB (varies by network) | + +:::warning +Running full Ethereum nodes requires significant disk space. Mainnet execution clients can require 1+ TB of storage. +::: + +## Architecture overview + +``` ++---------------------------------------------------------+ +| Obol Stack | ++---------------------------------------------------------+ +| obol CLI | +| +-- stack (init, up, down, purge) | +| +-- agent (init) | +| +-- openclaw (dashboard, setup, sync, skills, ...) | +| +-- model (configure, status) | +| +-- network (list, install, sync, delete) | +| +-- app (install, sync, list, delete) | +| +-- tunnel (status, login, provision) | +| +-- kubectl / helm / helmfile / k9s | ++---------------------------------------------------------+ +| k3d Cluster | +| +-- Traefik Gateway (ports 80, 8080, 443, 8443) | +| +-- Cloudflared (public tunnel) | +| +-- llmspy (LLM gateway) | +| +-- ERPC (RPC load balancer) | +| +-- Obol Frontend (web dashboard) | +| +-- Monitoring (Prometheus) | ++---------------------------------------------------------+ +| Deployments | +| +-- openclaw- (AI agent + remote-signer) | +| +-- ethereum- (blockchain network) | +| +-- aztec- (blockchain network) | +| +-- redis- (installed app) | ++---------------------------------------------------------+ +``` + +## Need assistance? + +If you have questions or encounter issues with Obol Stack, head over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.9/obol-stack/faq.md b/versioned_docs/version-v1.9/obol-stack/faq.md new file mode 100644 index 0000000000..435abe6798 --- /dev/null +++ b/versioned_docs/version-v1.9/obol-stack/faq.md @@ -0,0 +1,232 @@ +--- +description: "Frequently asked questions about Obol Stack" +sidebar_label: "FAQ" +slug: /obol-stack/faq +--- + +# FAQ + +## General + +### What is Obol Stack? + +The Obol Stack is a local Kubernetes-based environment for running AI agents alongside blockchain infrastructure. It uses k3d (Kubernetes in Docker) to provide a lightweight cluster where you can deploy an AI agent (OpenClaw), Ethereum nodes, Layer 2 networks, and other applications. + +### Is Obol Stack suitable for production? + +No. Obol Stack is designed for local development, testing, and experimentation. For production deployments, use dedicated infrastructure with proper security, redundancy, and monitoring. + +### What operating systems are supported? + +* **macOS** (Darwin) - Intel and Apple Silicon +* **Linux** - amd64 and arm64 architectures + +Windows is not currently supported. Windows users can use WSL2 to run the Obol Stack. + +### What are the hardware requirements? + +| Resource | Minimum | Recommended | +| ----------- | ------- | ----------------------------------- | +| **CPU** | 4 cores | 8+ cores | +| **RAM** | 8 GB | 16+ GB | +| **Storage** | 50 GB | 500 GB - 2 TB (depends on networks) | + +:::info +Running multiple networks or full Ethereum mainnet nodes significantly increases resource requirements. +::: + +## Installation + +### The installer fails with "Docker daemon not running" + +Ensure Docker is installed and running: + +```shell +# Check Docker status +docker info + +# Start Docker (macOS) +open -a Docker + +# Start Docker (Linux) +sudo systemctl start docker +``` + +### How do I update the Obol Stack? + +Re-run the installer: + +```shell +bash <(curl -s https://stack.obol.org) +``` + +The installer will update the CLI binary while preserving your configuration and data. + +### How do I uninstall Obol Stack? + +```shell +obol stack purge -f +rm -f ~/.local/bin/{obol,kubectl,helm,k3d,helmfile,k9s,obolup.sh} +rm -rf ~/.config/obol ~/.local/share/obol +``` + +### The installer cannot modify /etc/hosts + +Manually add the entry: + +```shell +echo "127.0.0.1 obol.stack" | sudo tee -a /etc/hosts +``` + +## AI Agent (OpenClaw) + +### How do I set up the agent? + +```shell +obol agent init +``` + +This runs the interactive OpenClaw onboard flow, which prompts you to choose a model provider (Ollama, Anthropic, or OpenAI). + +### How do I change the model provider? + +```shell +obol openclaw setup +``` + +Or configure the global model gateway directly: + +```shell +obol model setup +``` + +### How do I open the agent dashboard? + +```shell +obol openclaw dashboard +``` + +This starts a port-forward and opens the web UI in your browser. + +### How do I get the gateway token? + +```shell +obol openclaw token +``` + +:::info +When only one OpenClaw instance is installed, the instance ID is auto-selected. With multiple instances, specify the name: `obol openclaw dashboard my-agent`. +::: + +## Stack operations + +### The cluster fails to start + +**Port conflicts:** + +Obol Stack uses ports 80, 443, 8080, and 8443. Check for conflicts: + +```shell +lsof -i :8080 +lsof -i :8443 +``` + +If ports 80/443 conflict, edit `~/.config/obol/k3d.yaml` and remove the `80:80` and `443:443` entries (keep `8080:80` and `8443:443`). Access at `http://obol.stack:8080` instead. + +**Previous cluster not cleaned up:** + +```shell +k3d cluster delete --all +obol stack init --force +obol stack up +``` + +### Can I use my existing kubectl configuration? + +Obol Stack uses an isolated kubeconfig at `~/.config/obol/kubeconfig.yaml`. To use it with standard kubectl: + +```shell +export KUBECONFIG=~/.config/obol/kubeconfig.yaml +kubectl get nodes +``` + +### How do I persist data across cluster restarts? + +Data is automatically persisted. `obol stack down` stops the cluster but keeps data in `~/.local/share/obol/`. Only `obol stack purge -f` deletes persistent data. + +## Networks + +### How do I know which deployment ID was generated? + +The deployment ID is displayed when you run `obol network install`. You can also list deployments: + +```shell +ls ~/.config/obol/networks/ +``` + +### Can I run multiple instances of the same network? + +Yes. Each deployment gets a unique namespace: + +```shell +obol network install ethereum --id=mainnet --network=mainnet +obol network install ethereum --id=hoodi --network=hoodi +``` + +### How long does it take to sync an Ethereum node? + +| Network | Client | Approximate Time | +| ------- | ------ | ---------------- | +| Hoodi | Reth | 2-6 hours | +| Hoodi | Geth | 4-12 hours | +| Mainnet | Reth | 1-3 days | +| Mainnet | Geth | 3-7 days | + +:::info +Sync times depend on hardware, network connection, and chain state. +::: + +### My network deployment is stuck in Pending state + +```shell +obol kubectl describe pod -n +obol kubectl get events -n +obol kubectl get pvc -n +``` + +Common causes: insufficient Docker resources, PVC not bound, image pull errors. + +## Troubleshooting + +### Error: "stack not running, use 'obol stack up' first" + +Start the cluster: + +```shell +obol stack up +``` + +### Error: "deployment not found" + +Check your deployment ID: + +```shell +ls ~/.config/obol/networks/ +obol network sync ethereum/correct-id +``` + +### How do I report a bug? + +Report issues on GitHub: [https://github.com/ObolNetwork/obol-stack/issues](https://github.com/ObolNetwork/obol-stack/issues) + +Include: + +* Obol Stack version (`obol version`) +* Operating system and architecture +* Docker version (`docker version`) +* Steps to reproduce +* Relevant logs + +## Need more help? + +Head over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.9/obol-stack/installing-apps.md b/versioned_docs/version-v1.9/obol-stack/installing-apps.md new file mode 100644 index 0000000000..ac97d24f72 --- /dev/null +++ b/versioned_docs/version-v1.9/obol-stack/installing-apps.md @@ -0,0 +1,117 @@ +--- +description: "Deploy additional applications on your Obol Stack" +sidebar_label: "Installing Apps" +slug: /obol-stack/installing-apps +--- + +# Installing Apps + +The Obol Stack supports installing arbitrary Helm charts as managed applications. Each installation creates an isolated deployment with its own namespace, similar to network deployments. + +## Install an application + +Install any Helm chart using one of the supported reference formats: + +```shell +# Install from ArtifactHub (repo/chart format) +obol app install bitnami/redis + +# Specific version +obol app install bitnami/postgresql@15.0.0 + +# Direct URL to chart archive +obol app install https://charts.bitnami.com/bitnami/redis-19.0.0.tgz + +# Custom name and deployment ID +obol app install bitnami/postgresql --name mydb --id production +``` + +:::info +Find charts at [Artifact Hub](https://artifacthub.io). +::: + +**Supported chart reference formats:** + +| Format | Example | +| -------------------- | ------------------------------------------ | +| `repo/chart` | `bitnami/redis` (resolved via ArtifactHub) | +| `repo/chart@version` | `bitnami/redis@19.0.0` | +| `https://.../*.tgz` | Direct URL to chart archive | + +**What happens during installation:** + +1. Resolves the chart reference (via ArtifactHub for `repo/chart` format). +2. Fetches default values from the chart. +3. Generates a `helmfile.yaml` that references the chart remotely. +4. Saves configuration to `~/.config/obol/applications///`. + +## Deploy to the cluster + +After installing, deploy the application: + +```shell +obol app sync postgresql/eager-fox +``` + +Check status: + +```shell +obol kubectl get all -n postgresql-eager-fox +``` + +## List applications + +```shell +# Simple list +obol app list + +# Detailed output +obol app list --verbose +``` + +## Customize configuration + +Edit the values file before deploying or re-syncing: + +```shell +$EDITOR ~/.config/obol/applications/postgresql/eager-fox/values.yaml + +# Re-deploy with changes +obol app sync postgresql/eager-fox +``` + +**Local files per deployment:** + +* `helmfile.yaml` - Deployment configuration (references chart remotely) +* `values.yaml` - Configuration values (edit to customize) + +## Delete an application + +```shell +# With confirmation prompt +obol app delete postgresql/eager-fox + +# Skip confirmation +obol app delete postgresql/eager-fox --force +``` + +This removes the Kubernetes namespace, all deployed resources, and the local configuration directory. + +## Default infrastructure + +The following services are deployed automatically when the stack starts (you do not need to install them): + +| Service | Namespace | Purpose | +| ----------------- | --------------- | ------------------------------------------------ | +| **ERPC** | `erpc` | Unified RPC load balancer for Ethereum endpoints | +| **Obol Frontend** | `obol-frontend` | Web management dashboard | +| **Monitoring** | `monitoring` | Prometheus + kube-prometheus-stack | +| **Traefik** | `traefik` | Gateway API ingress controller | +| **Cloudflared** | `traefik` | Cloudflare tunnel connector | +| **llmspy** | `llm` | LLM proxy/router | + +View all running services: + +```shell +obol helm list -A +``` diff --git a/versioned_docs/version-v1.9/obol-stack/installing-networks.mdx b/versioned_docs/version-v1.9/obol-stack/installing-networks.mdx new file mode 100644 index 0000000000..11f50abd19 --- /dev/null +++ b/versioned_docs/version-v1.9/obol-stack/installing-networks.mdx @@ -0,0 +1,205 @@ +--- +description: "Deploy blockchain networks on your local Obol Stack" +sidebar_label: "Installing Networks" +slug: /obol-stack/installing-networks +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Installing Networks + +The Obol Stack supports installing multiple blockchain networks on your local Kubernetes cluster. Each network installation creates a unique deployment with its own namespace, allowing you to run multiple instances simultaneously. + +## Available networks + +View all available networks: + +```shell +obol network list +``` + +Currently supported networks: + +| Network | Description | +| ------------ | -------------------------------------------------- | +| **ethereum** | Full Ethereum node (execution + consensus clients) | +| **aztec** | Aztec Layer 2 sequencer node | + +## Network installation workflow + +Installing a network follows a two-step process: + +1. **Install** - Generate configuration and save to disk +2. **Sync** - Deploy the configuration to the cluster + +This separation allows you to review and modify configuration before deployment. + +### Install command + +```shell +obol network install [flags] +``` + +This creates a deployment directory at `~/.config/obol/networks///` containing: + +* `values.yaml` - Configuration values (editable) +* `helmfile.yaml` - Deployment definition + +### Sync command + +```shell +obol network sync / +``` + +This deploys the configuration to your Kubernetes cluster using Helmfile. + +### Delete command + +```shell +obol network delete / +``` + +This removes both the Kubernetes resources and local configuration. + +## Ethereum network + +Deploy a full Ethereum node with configurable execution and consensus clients. + +### Configuration options + +| Flag | Description | Options | Default | +| -------------------- | ---------------------- | --------------------------------------------------- | -------------- | +| `--id` | Deployment identifier | Any string | Auto-generated | +| `--network` | Ethereum network | mainnet, hoodi | mainnet | +| `--execution-client` | Execution layer client | reth, geth, nethermind, besu, erigon, ethereumjs | reth | +| `--consensus-client` | Consensus layer client | lighthouse, prysm, teku, nimbus, lodestar, grandine | lighthouse | + +### Examples + + + +Deploy an Ethereum node on Hoodi testnet with default clients: + +```shell +# Install configuration +obol network install ethereum --network=hoodi + +# Deploy to cluster (replace with your deployment ID) +obol network sync ethereum/knowing-wahoo +``` + + + +Deploy a mainnet node with Geth and Prysm: + +```shell +obol network install ethereum \ + --id=mainnet-prod \ + --network=mainnet \ + --execution-client=geth \ + --consensus-client=prysm + +obol network sync ethereum/mainnet-prod +``` + + + +Run mainnet and testnet nodes simultaneously: + +```shell +obol network install ethereum --id=mainnet --network=mainnet +obol network install ethereum --id=hoodi --network=hoodi + +obol network sync ethereum/mainnet +obol network sync ethereum/hoodi +``` + + + +:::warning +Full Ethereum nodes require significant resources. Mainnet execution clients need 1+ TB of storage and can take days to sync. Consider using testnets for development. +::: + +### Check sync status + +```shell +# View pod status +obol kubectl get pods -n ethereum- + +# Check execution client logs +obol kubectl logs -n ethereum- -l app=execution -f + +# Check consensus client logs +obol kubectl logs -n ethereum- -l app=consensus -f +``` + +## Aztec network + +Deploy an Aztec Layer 2 sequencer node for the privacy-focused Ethereum rollup. + +### Configuration options + +| Flag | Description | Options | Default | +| ------------------------ | -------------------------- | ---------- | --------------- | +| `--id` | Deployment identifier | Any string | Auto-generated | +| `--network` | Aztec network | mainnet | mainnet | +| `--attester-private-key` | Attester private key (hex) | Required | None | +| `--l1-execution-url` | L1 execution RPC URL | URL | ERPC endpoint | +| `--l1-consensus-url` | L1 consensus RPC URL | URL | Public endpoint | + +### Example + +```shell +obol network install aztec \ + --attester-private-key= \ + --l1-execution-url=https://geth-prysm-mainnet-1.gcp.obol.tech/ \ + --l1-consensus-url=https://prysm-geth-mainnet-1.gcp.obol.tech/ +``` + +Deploy to the cluster: + +```shell +obol network sync aztec/ +``` + +:::info +You can use your own Ethereum node endpoints or the in-cluster ERPC endpoint by changing the L1 URL flags. +::: + +### Resource requirements + +| Resource | Request | Limit | +| ----------- | ------- | ------- | +| **CPU** | 4 cores | 8 cores | +| **Memory** | 16 GB | 32 GB | +| **Storage** | 1 TB | - | + +:::warning +Ensure your machine has sufficient resources before deploying an Aztec node. +::: + +## Managing deployments + +### View deployment status + +```shell +obol kubectl get namespaces | grep -E "ethereum|aztec" +``` + +### Modify configuration + +```shell +$EDITOR ~/.config/obol/networks///values.yaml +obol network sync / +``` + +### Delete a deployment + +```shell +obol network delete / +``` + +:::warning +Deletion is permanent. All blockchain data stored in the deployment will be lost. +::: diff --git a/versioned_docs/version-v1.9/obol-stack/quickstart.mdx b/versioned_docs/version-v1.9/obol-stack/quickstart.mdx new file mode 100644 index 0000000000..8eeeae6939 --- /dev/null +++ b/versioned_docs/version-v1.9/obol-stack/quickstart.mdx @@ -0,0 +1,166 @@ +--- +description: "Get started with Obol Stack in under 5 minutes" +sidebar_label: "Quickstart" +slug: /obol-stack/quickstart +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Quickstart + +This guide walks you through installing the Obol Stack, setting up an AI agent, and optionally deploying a blockchain network. + +## Prerequisites + +* Docker installed and running on your machine. +* macOS or Linux operating system. +* At least 8 GB of RAM available. + +:::info +Ensure Docker is running before proceeding. You can verify this by running `docker info` in your terminal. +::: + +## Step 1: Install Obol Stack + +Run the bootstrap installer: + +```shell +bash <(curl -s https://stack.obol.org) +``` + +The installer will: + +1. Validate that Docker is running. +2. Install the `obol` CLI binary and dependencies (kubectl, helm, k3d, helmfile, k9s). +3. Configure your PATH and add `obol.stack` to `/etc/hosts`. +4. Offer to start the cluster immediately. + + + +```shell +bash <(curl -s https://stack.obol.org) +``` + +Files are installed to: + +* Config: `~/.config/obol/` +* Data: `~/.local/share/obol/` +* Binaries: `~/.local/bin/` + + + +```shell +OBOL_RELEASE=v0.1.0 bash <(curl -s https://stack.obol.org) +``` + + + +```shell +git clone https://github.com/ObolNetwork/obol-stack.git +cd obol-stack +OBOL_DEVELOPMENT=true ./obolup.sh +``` + +Development mode uses a local `.workspace/` directory and runs `go run` instead of a compiled binary. + + + +## Step 2: Start the stack + +```shell +obol stack init +obol stack up +``` + +:::info +The first startup may take a few minutes as Docker pulls the required images. +::: + +## Step 3: Set up the AI agent + +Initialize an OpenClaw agent instance: + +```shell +obol agent init +``` + +This walks you through choosing a model provider: + +* **Ollama** (local, free) - if Ollama is detected on your machine +* **Anthropic** or **OpenAI** - routed through the in-cluster llmspy gateway + +Once complete, open the agent dashboard: + +```shell +obol openclaw dashboard +``` + +Each agent is automatically provisioned with an Ethereum signing wallet (via the remote-signer service). The wallet address is displayed during setup. + +:::tip +You can reconfigure the model provider at any time with `obol openclaw setup`. +::: + +## Step 4: Deploy a blockchain network (optional) + +Install an Ethereum node on the Hoodi testnet: + +```shell +obol network install ethereum --network=hoodi +``` + +Deploy it to the cluster (replace with your deployment ID): + +```shell +obol network sync ethereum/ +``` + +:::warning +Replace the ID with the actual deployment ID shown in your terminal output (e.g., `knowing-wahoo`). +::: + +Check the deployment: + +```shell +obol kubectl get pods -n ethereum- +``` + +## Step 5: Explore + +```shell +# Interactive cluster UI +obol k9s + +# View all pods +obol kubectl get pods -A + +# Check tunnel status (public URL) +obol tunnel status + +# Configure model provider globally +obol model setup +``` + +## Stopping and cleaning up + +```shell +# Stop the cluster (preserves data) +obol stack down + +# Restart +obol stack up + +# Remove everything including data +obol stack purge -f +``` + +:::warning +`obol stack purge -f` is irreversible. It removes all cluster data and configuration. +::: + +## Next steps + +* [Installing networks](installing-networks.mdx) - Deploy different blockchain networks. +* [Installing apps](installing-apps.md) - Deploy additional applications. +* [FAQ](faq.md) - Common questions and troubleshooting. diff --git a/versioned_docs/version-v1.9/run-a-dv/editing/README.md b/versioned_docs/version-v1.9/run-a-dv/editing/README.md new file mode 100644 index 0000000000..d3b944849e --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/editing/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Edit a Cluster" +slug: /run-a-dv/editing +--- + +# Edit a Cluster + diff --git a/versioned_docs/version-v1.9/run-a-dv/editing/add-operators.md b/versioned_docs/version-v1.9/run-a-dv/editing/add-operators.md new file mode 100644 index 0000000000..a53d7eb8b2 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/editing/add-operators.md @@ -0,0 +1,99 @@ +--- +description: "Add operators to your existing distributed validator cluster using the charon alpha edit add-operators command." +sidebar_label: "Adding Operators" +slug: /run-a-dv/editing/add-operators +--- + +# Adding Operators + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can add operators to your cluster using the `charon alpha edit add-operators` command. This operation keeps all distributed validator public keys unchanged whilst adding new operators to the cluster. + +## Prerequisites + +1. Review the `edit add-operators` command [CLI reference](../../learn/charon/charon-cli-reference.md#add-operators-to-a-cluster). +2. **For existing operators**: Keep the DV node running during the process and ensure you have a copy of the current [cluster lock file](../../learn/charon/cluster-configuration/#cluster-lock-file) and validator private key shares. +3. **For new operators**: Obtain a copy of the existing cluster lock file from the existing operators and have your Charon ENR private key file ready. +4. Obtain the Charon ENR addresses of all new operators being added to the cluster. + +:::info +The command uses a different set of p2p-relays to `charon run` to avoid conflicts with your running cluster. +::: + +## Adding Operators Process + +The examples below demonstrate adding new operators to an existing cluster. All existing operators must run this command, along with the new operators being added. + +### For Existing Operators + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --output-dir=/opt/charon/output +``` + +### For New Operators + +New operators being added should run the same command but only need to provide their private key file and the cluster lock file (they won't have validator keys yet): + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --output-dir=output --lock-file=cluster-lock.json --private-key-file=charon-enr-private-key + +# Or, if you prefer running it in Docker +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:latest alpha edit add-operators --new-operator-enrs=enr:-JG4QH... --private-key-file=/opt/charon/charon-enr-private-key --lock-file=/opt/charon/cluster-lock.json --output-dir=/opt/charon/output +``` + +:::info +To add multiple operators at once, provide a comma-separated list: `--new-operator-enrs=enr:-JG4QH...,enr:-JG4QK...,enr:-JG4QL...` +::: + +This command will create a new cluster configuration with the additional operators whilst keeping all validator public keys unchanged. The new configuration will be saved in the `output` directory. + +## Making the DV Stack Use the New Configuration + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +1. To start using the new configuration (with the added operators), stop the current Charon and validator client instances: + +```bash +# Stop the containers +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +# Put the original artifacts in a backup location +mv .charon .charon-backup +# Copy the output from the add-operators command into the location of the original files +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +# Restart charon and the validator client with the new data +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` and recognise all validators in the cluster with the updated operator set. + +:::warning +All existing operators must fully shut down their cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the expanded operator set can begin operating. Unlike add-validators, this is not a gradual migration. + +It is advisable to shut the cluster down for at least two epochs, to minimise any risk of unintended double signing during the controlled restart. +::: + +## Current Considerations + +* The new cluster configuration will not yet be reflected on the Obol Launchpad. +* The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +* All operators (both existing and new) must participate in the add-operators ceremony for it to complete successfully. +* The cluster's threshold value remains unchanged after adding operators because the existing set of operators already possesses enough shares to create full signatures. diff --git a/versioned_docs/version-v1.9/run-a-dv/editing/add-validators.md b/versioned_docs/version-v1.9/run-a-dv/editing/add-validators.md new file mode 100644 index 0000000000..eae37a17c1 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/editing/add-validators.md @@ -0,0 +1,77 @@ +--- +description: "Add validators to your existing distributed validator cluster using the charon alpha edit add-validators command." +sidebar_label: "Adding Validators" +slug: /run-a-dv/editing/add-validators +--- + +# Adding Validators + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can add validators to your cluster using the `charon alpha edit add-validators` command. The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) and assumes a Lodestar validator, but the process is similar for other setups. + +## Prerequisites + +1. Review the `edit add-validators` command [CLI reference](../../learn/charon/charon-cli-reference.md#add-validators-to-a-cluster). +2. Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares (or use `--unverified` if validator keys are not accessible). + +:::info +The command uses a different set of p2p-relays to `charon run` to avoid conflicts with your running cluster. +::: + +## Adding Validators Process + +The examples below are for adding 10 validators. You can use them with any number of validators you would like to add. Run the following command to collectively generate and add 10 new validators with other node operators (similar to DKG): + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit add-validators --num-validators 10 --withdrawal-addresses=0x --fee-recipient-addresses=0x --output-dir=/opt/charon/output +``` + +This command will create a new cluster configuration that includes both existing and new validators. It will also generate the necessary keys for the new validators and deposit data files. The new configuration will be saved in the `output` directory. + +## Making the DV Stack Use the New Validators + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +1. To start using the new configuration (with the added validators), stop the current Charon and validator client instances: + +```bash +# Stop the containers +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +# Put the original artifacts in a backup location +mv .charon .charon-backup +# Copy the output from the add-validators command into the location of the original files +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +# Restart charon and the validator client with the new data +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` and recognise all validators in the cluster. + +:::info +Steps 1–3 must be performed independently by all node operators, likely at different times. During this process, some nodes will use the old configuration and others the new one. Once the number of upgraded nodes reaches the BFT threshold, the newly added validators will begin participating in the cluster. +::: + +## Current Considerations + +* The new cluster configuration will not be reflected on the Obol Launchpad. +* The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster under a different identifier. +* If Charon has no access to the existing validator keys (for example, if they're stored in a remote KeyManager), you must use the `--unverified` flag. This flag allows the addition to proceed but skips hashing and signing the new cluster lock data. However when using cluster artifacts created with this flag, you must start `charon run` with the `--no-verify` flag or set the `CHARON_NO_VERIFY=true` environment variable. +* If you use different validator clients, review the keys import script. The old keys in `.charon/validator_keys` remain unchanged, so verify that importing the same keys will not disrupt the validator client's state. diff --git a/versioned_docs/version-v1.9/run-a-dv/editing/recreate-private-keys.md b/versioned_docs/version-v1.9/run-a-dv/editing/recreate-private-keys.md new file mode 100644 index 0000000000..2c3f08d554 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/editing/recreate-private-keys.md @@ -0,0 +1,125 @@ +--- +description: "Create new private key shares for your existing distributed validator cluster using the charon alpha edit recreate-private-keys command." +sidebar_label: "Recreating Private Keys" +slug: /run-a-dv/editing/recreate-private-keys +--- + +# Recreating Private Keys + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can recreate the private key shares for your cluster using the `charon alpha edit recreate-private-keys` command. This operation creates new private key shares to replace the existing validator private keys whilst retaining the same operator identities and validator public keys. + +## When to Use This Feature + +You might need to recreate private key shares in several scenarios: + +* **Security concerns**: If you suspect that private key shares may have been compromised +* **Key rotation**: As part of regular security practices to rotate cryptographic material +* **Recovery**: After a security incident where you want to refresh all key material +* **Compliance**: Meeting organisational policies that require periodic key rotation + +:::info +This operation maintains the same validator public keys, so your validators remain registered on the beacon chain without any changes. Only the underlying private key shares held by operators are refreshed. +::: + +## Prerequisites + +1. Review the `edit recreate-private-keys` command [CLI reference](../../learn/charon/charon-cli-reference.md#recreate-private-key-shares). +2. Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares. +3. All operators in the cluster must participate in this ceremony. +4. Each operator must have their current validator private key shares available. + +:::info +The ceremony uses a different p2p relay from your running cluster to avoid conflicts. The default relay address is already configured differently, so no special action is required. +::: + +## Recreating Private Keys Process + +All operators must run this command simultaneously. The ceremony will coordinate between all operators to generate new private key shares. + +```bash +# If you prefer running a pre-built charon binary +charon alpha edit recreate-private-keys --output-dir=output + +# Or, if you prefer running it in Docker +# (replace 'latest' with the most recent version if needed: https://hub.docker.com/r/obolnetwork/charon/tags) +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit recreate-private-keys --output-dir=/opt/charon/output +``` + +This command will: + +1. Use the existing cluster configuration and operator identities +2. Generate new private key shares for all validators +3. Create a new cluster lock file with updated key shares +4. Save the new configuration in the `output` directory + +:::info +The ceremony requires all operators to participate. If any operator is unavailable, the ceremony cannot complete. +::: + +## Making the DV Stack Use the New Keys + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +:::danger +**Critical Security Step**: All operators must coordinate to switch to the new keys at approximately the same time to avoid validation failures. Plan a maintenance window and communicate clearly with all operators. +::: + +1. To start using the new keys, stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +Lodestar's boot script (`lodestar/run.sh`) will automatically import all keys, removing any existing keys and cache. Charon will load the new `cluster-lock.json` with the recreated private key shares. + +:::warning +All operators must fully shut down their existing cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the recreated private keys can begin operating. Steps 1–3 must be performed by all node operators within a coordinated maintenance window to minimise downtime. +::: + +## Verifying the New Configuration + +After all operators have restarted with the new keys, verify that: + +1. All Charon nodes are connected and healthy +2. The cluster is successfully producing attestations +3. No error messages appear in the logs related to signature verification + +```bash +# Check Charon logs +docker compose logs -f charon + +# Verify cluster health in the monitoring dashboard +# Check that all validators are attesting normally +``` + +## Security Best Practices + +* **Secure deletion**: After successfully transitioning to the new keys and verifying operation, securely delete the old key shares +* **Coordination**: Ensure all operators are prepared and available during the planned maintenance window +* **Communication**: Maintain clear communication channels between all operators throughout the process +* **Backup**: Keep the backup until you've verified that the cluster is operating normally with the new keys for at least several epochs + +## Current Limitations + +* The new cluster configuration will not be reflected on the Launchpad. +* The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +* All operators must participate in the ceremony; there is no option for partial participation. +* All operators must have their current validator private key shares available for the ceremony to succeed. +* The transition period requires coordination to minimise validator downtime. diff --git a/versioned_docs/version-v1.9/run-a-dv/editing/remove-operators.md b/versioned_docs/version-v1.9/run-a-dv/editing/remove-operators.md new file mode 100644 index 0000000000..382a9da077 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/editing/remove-operators.md @@ -0,0 +1,131 @@ +--- +description: "Remove operators from your existing distributed validator cluster using the charon alpha edit remove-operators command." +sidebar_label: "Removing Operators" +slug: /run-a-dv/editing/remove-operators +--- + +# Removing Operators + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can remove operators from your cluster using the `charon alpha edit remove-operators` command. This operation leaves all validators intact whilst removing specified operators from the cluster. + +## Prerequisites + +1. Review the `edit remove-operators` command [CLI reference](../../learn/charon/charon-cli-reference.md#remove-operators-from-a-cluster). +2. **For remaining operators**: Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares. +3. **For operators being removed**: A copy of the cluster lock file is required to participate in the ceremony (if participating). +4. Identify the Charon ENR addresses of the operators you wish to remove from the cluster. + +:::info +The ceremony uses a different p2p relay from your running cluster to avoid conflicts. The default relay address is already configured differently, so no special action is required. +::: + +## Understanding Fault Tolerance + +Before removing operators, it's crucial to understand your cluster's fault tolerance: + +* **Fault tolerance (f)** = `number of operators - threshold` +* If you're removing **more operators than the fault tolerance**, you must use the `--participating-operator-enrs` flag to specify which operators will participate in the ceremony. + +For example, if your cluster has 4 operators with a threshold of 3 (f=1), removing 2 operators requires specifying at least 3 participating operators. + +## Removing Operators Process + +### Standard Removal (Within Fault Tolerance) + +If you're removing operators within the fault tolerance, all remaining operators can participate automatically: + +```bash +# For remaining operators +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --output-dir=output + +# Docker version +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --output-dir=/opt/charon/output +``` + +### Advanced Removal (Exceeding Fault Tolerance) + +If you're removing more operators than the fault tolerance allows, you must specify participating operators: + +```bash +# For participating operators (both remaining and being removed) +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH...,enr:-JG4QK... --participating-operator-enrs=enr:-JG4QL...,enr:-JG4QM...,enr:-JG4QN... --output-dir=output + +# Docker version +docker run --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH...,enr:-JG4QK... --participating-operator-enrs=enr:-JG4QL...,enr:-JG4QM...,enr:-JG4QN... --output-dir=/opt/charon/output +``` + +:::info +When using `--participating-operator-enrs`, you must have at least `threshold` number of operators participating. Operators being removed can participate if explicitly included in this list. +::: + +### For Operators Being Removed + +Operators being removed have two options: + +1. **If participating** (when explicitly included in `--participating-operator-enrs`): Run the same command as other participants with the `--output-dir` flag +2. **If not participating**: Do not run the command at all; simply ignore the ceremony + +```bash +# For removed operators who are participating in the ceremony +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --participating-operator-enrs=enr:-JG4QH...,enr:-JG4QK...,enr:-JG4QL... --private-key-file=.charon/charon-enr-private-key --lock-file=.charon/cluster-lock.json --validator-keys-dir=.charon/validator_keys --output-dir=output +``` + +## Customising the Threshold + +By default, the new threshold is calculated as `ceil(n * 2 / 3)`, where `n` is the new number of operators. You can override this with the `--new-threshold` flag: + +```bash +charon alpha edit remove-operators --operator-enrs-to-remove=enr:-JG4QH... --new-threshold=3 --output-dir=output +``` + +:::danger +Using a non-default threshold value decreases security. All operators must use the same value. Only override this if you fully understand the implications. +::: + +## Making the DV Stack Use the New Configuration + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +### For Remaining Operators + +1. Stop the current Charon and validator client instances: + +```bash +docker compose stop charon lodestar +``` + +2. Back up and remove the existing `.charon` directory, then move the `output` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv output .charon +``` + +3. Restart the Charon and validator client instances: + +```bash +docker compose up -d charon lodestar +``` + +:::warning +All remaining operators must fully shut down their existing cluster nodes before starting with the new configuration. The old cluster must be completely stopped before the new cluster with the reduced operator set can begin operating. +::: + +### For Removed Operators + +Operators who have been removed can safely shut down their nodes after the ceremony completes: + +```bash +docker compose down +``` + +## Current Limitations + +* The new cluster configuration will not be reflected on the Launchpad. +* The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +* All remaining operators must have valid validator keys to participate in the removal ceremony. +* When removing more operators than the fault tolerance, at least `threshold` operators must participate in the ceremony. diff --git a/versioned_docs/version-v1.9/run-a-dv/editing/replace-operator.md b/versioned_docs/version-v1.9/run-a-dv/editing/replace-operator.md new file mode 100644 index 0000000000..0cae7509b1 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/editing/replace-operator.md @@ -0,0 +1,116 @@ +--- +description: "Replace an operator in your existing distributed validator cluster using the charon alpha edit replace-operator command." +sidebar_label: "Replace an Operator" +slug: /run-a-dv/editing/replace-operator +--- + +# Replace an Operator + +:::warning +This is an alpha feature and is not yet recommended for production use. +::: + +You can replace an operator in your cluster using the `charon alpha edit replace-operator` command. This operation keeps all validators intact whilst swapping one operator for another in the cluster. + +## Prerequisites + +1. Review the `edit replace-operator` command [CLI reference](../../learn/charon/charon-cli-reference.md#replace-an-operator-in-a-cluster). +2. **For continuing operators**: Keep the DV node running during the process and ensure you have a copy of the current cluster lock file and validator private key shares. +3. **For the new operator**: Obtain a copy of the existing cluster lock file from the continuing operators and have your Charon ENR private key file ready. +4. **For the old operator being replaced**: The operator being replaced should NOT participate in the ceremony. +5. Identify the Charon ENR address of the operator you wish to replace and have the new operator's ENR ready. + +:::info +The ceremony uses a different p2p relay from your running cluster to avoid conflicts. The default relay address is already configured differently, so no special action is required. +::: + +## Understanding the Replacement Process + +The replace-operator ceremony performs a one-for-one swap: + +* The **old operator** is completely removed from the cluster and does not participate in the ceremony +* The **new operator** takes over at the same index position as the old operator +* All **continuing operators** must participate with their existing validator keys +* All validator public keys remain unchanged + +This is more convenient than `remove-operators` followed by `add-operators`, as it maintains the cluster size and threshold in a single atomic operation. + +## Replacing an Operator + +All continuing operators and the new operator must run this command. The old operator being replaced should NOT run the command. + +### For Continuing Operators + +```bash +# Standard usage +charon alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... + +# Docker version +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... +``` + +### For the New Operator + +The new operator being added should run the same command but only needs to provide their private key file and the cluster lock file (they won't have validator keys yet): + +```bash +# Standard usage +charon alpha edit replace-operator --old-operator-enr=enr:-JG4QH... --new-operator-enr=enr:-JG4QK... --output-dir=output --lock-file=cluster-lock.json --private-key-file=charon-enr-private-key + +# Docker version +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon" -w "/opt/charon" obolnetwork/charon:latest alpha edit replace-operator --old-operator-enr=enr:-HW4...UVM --new-operator-enr=enr:-HW4QB-SH7cQ....2A0g6y0 +``` + +### For the Old Operator Being Replaced + +The old operator **should not participate** in the ceremony. Simply do not run the command. + +:::warning +The old operator's ENR and new operator's ENR must be different. The command will fail if they are the same. +::: + +## Making the DV Stack Use the New Configuration + +The example below is designed for the [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node), but the process is similar for other setups. + +:::danger +The old cluster **must be shut down for at least two epochs**. If you're not sure of the epoch boundary, wait 18 minutes from the original cluster going offline until you turn on the modified cluster. **Failure to heed this warning may result in slashing**. +::: + +### For Continuing Operators and New Operator + +1. Stop the current Charon and validator client instances: + +```bash +docker compose down +``` + +2. Back up and remove the existing `.charon` directory, then move the `distributed_validator` directory to `.charon`: + +```bash +mv .charon .charon-backup +mv distributed_validator .charon +``` + +3. Restart the Charon and validator client instances **once at least two epochs of downtime have passed**: + +```bash +docker compose up -d +``` + +### For the Old Operator Being Replaced + +The operator who has been replaced can safely shut down their node after the ceremony completes: + +```bash +docker compose down +``` + +## Current Limitations + +* The new cluster configuration will not be reflected on the Launchpad. +* The new cluster configuration will have a new cluster hash, so the observability stack will display new cluster data under a different identifier. +* All continuing operators must have valid validator keys to participate in the replacement ceremony. +* The cluster's threshold value remains unchanged after replacing an operator. +* The new operator's ENR must not already exist in the cluster. +* The old operator's ENR must exist in the current cluster. diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/README.md b/versioned_docs/version-v1.9/run-a-dv/integrations/README.md new file mode 100644 index 0000000000..a1b2dcacec --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Partner Integrations" +slug: /run-a-dv/integrations +--- + +# Partner Integrations + diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/create-an-eigenlayer-dv.mdx b/versioned_docs/version-v1.9/run-a-dv/integrations/create-an-eigenlayer-dv.mdx new file mode 100644 index 0000000000..e7922cce3b --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/create-an-eigenlayer-dv.mdx @@ -0,0 +1,57 @@ +--- +sidebar_label: "Create an EigenLayer DV" +slug: /run-a-dv/integrations/create-an-eigenlayer-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create an EigenLayer DV + +:::warning +The Obol-SDK is in a beta state and should be used with caution. Ensure you validate all important data. +::: + +This is a walkthrough of creating a distributed validator cluster pointing to an [EigenLayer](https://eigenlayer.xyz/) [EigenPod](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/), using the [DV Launchpad](../../learn/intro/launchpad.md) and other applications. + +### Pre-requisites {#pre-requisites} +* The Ethereum addresses or ENS names for the node operators in the cluster. (Currently the DV Launchpad only supports Metamask or equivalent injected web3 browser wallets.) +* If creating more than one validator, the ability to use the [obol-sdk](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) is required. + +### Create a SAFE to own the EigenPod {#create-a-safe-to-own-the-eigenpod} +Deploy a [SAFE](https://app.safe.global/) with the addresses of the node operators as signers. A reasonable signing threshold is the same as a cluster (>2/3rds) but use good judgement if a different threshold or signer set suits your use case. The principal ether for these validators will be returned to this address. + +### Create an EigenPod {#create-an-eigenpod} +Select the "Create EigenPod" option on the [EigenLayer App](https://app.eigenlayer.xyz/)'s 'Restake' page, using the created SAFE account via WalletConnect. Note the EigenPod's address. + +### Create a Splitter for the block reward {#create-a-splitter-for-the-block-reward} +Create a Splitter on [splits.org](https://app.splits.org/), to divide the block reward and MEV amongst the operators. Note the split's address. + +:::tip +To be recognised as a part of Obol's [1% for Decentralisation](https://blog.obol.tech/1-percent-for-decentralisation/) campaign, you must contribute 3% of execution layer rewards by setting [this address](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient on your split. Upcoming Obol EigenPods will support contributing 1% of total rewards instead of 3% of only execution rewards. +::: + +### Create the DV cluster invite {#create-the-dv-cluster-invite} +With these contracts deployed, you can now create the DV cluster invitation to send to Node Operators, this can be done through the DV Launchpad or the Obol SDK. + + + +* Use the "Create a cluster with a group" [flow](../start/create-a-dv-with-a-group.mdx) on the [DV Launchpad](../../learn/intro/launchpad.md). +* Choose a cluster name and invite your operator's addresses. +* When setting the withdrawal credentials, select "Custom". +* For "Withdrawal Address", set the EigenPod contract address. +* For "Fee Recipient", set the Split contract address. +* Continue the process of creating a cluster normally, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +* If you are creating a cluster with more than one validator, you will need to craft the cluster invitation with the [SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk). +* Follow the [Create a cluster using the SDK](../../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx) guide. +* For `withdrawal_address`, set the EigenPod contract address. +* For `fee_recipient_address`, set the Split contract address. +* Continue the process of creating the cluster as per the guide, share the invitation link with the operators and have them complete the Distributed Key Generation ceremony. + + + +### Deposit and restake your Distributed Validator {#deposit-and-restake-your-distributed-validator} +Once you have completed the DKG ceremony, you can continue the flow on the EigenLayer app to activate these validators and restake them. Consult the EigenLayer [documentation](https://docs.eigenlayer.xyz/eigenlayer/restaking-guides/restaking-user-guide/native-restaking/create-eigenpod-and-set-withdrawal-credentials/enable-restaking) to continue the process. diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/dappnode.md b/versioned_docs/version-v1.9/run-a-dv/integrations/dappnode.md new file mode 100644 index 0000000000..0bfe8e445f --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/dappnode.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "Run a DV on a DappNode" +slug: /run-a-dv/integrations/dappnode +--- + +# Run a DV on a DappNode + +For setup, see quickstart guide: + +For set-up of a DV using DappNode, see the quickstart guide [Create a DV Alone](../start/create-a-dv-alone.mdx), and select the appropriate tab for "DappNode". + +### Frequently asked questions {#frequently-asked-questions} +#### If an operator uses an ENR to join a cluster, then exits the validator key, do they need to clean up the validator and Charon volumes to use the same ENR for another cluster? {#if-an-operator-uses-an-enr-to-join-a-cluster-then-exits-the-validator-key-do-they-need-to-clean-up-t} +Yes, they need to clean up the Charon and validator volumes. However, instead of deleting everything, the operator can: + +1. Download a backup (keep a copy just in case). +2. Edit the backup, keeping only the necessary files from the specific cluster (see image below) + +![](/img/gitbook/image.png) + +3. Recompress the edited backup and upload it again after removing the Charon and validator volumes. + +#### Does an operator need to use the `VALIDATOR_EXTRA_OPTS` to pass the `builderonly` or `builderalways` flag for Lodestar VC? {#does-an-operator-need-to-use-the-validator_extra_opts-to-pass-the-builderonly-or-builderalways-flag} +No, if `ENABLE_MEV_BOOST` is set to `true`, these flags will be added automatically. + +![](/img/gitbook/image-90.png) + +#### How can users running two clusters (e.g., one for EtherFi solo stakers and another for Techne) on the same Dappnode machine push monitoring data from both clusters to Obol? {#how-can-users-running-two-clusters-eg-one-for-etherfi-solo-stakers-and-another-for-techne-on-the-sam} +In the Config tab, there is a field called "Charons to monitor by Obol (optional)". You just need to enter the cluster numbers you are using in Dappnode. For example, if you’re running three nodes on clusters 1, 2, and 3, you would enter “1,2,3”. diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/lido-csm.md b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-csm.md new file mode 100644 index 0000000000..dced8e67e6 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-csm.md @@ -0,0 +1,225 @@ +--- +description: "Setup and run a DV within the Lido Community Staking Module" +sidebar_label: "Create a Lido CSM DV" +slug: /run-a-dv/integrations/lido-csm +--- + +# Create a Lido CSM DV + +This is a guide on taking part in Lido's [Community Staking Module](https://lido.fi/csm) (CSM) with a squad as part of a [Distributed Validator Cluster](../../learn/intro/key-concepts.md#distributed-validator-cluster). + +To start, this guide makes a couple assumptions: + +1. You're running a Linux distribution and you've installed [Git](https://git-scm.com/downloads) and [Docker](https://docs.docker.com/engine/install/) (as a [non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). +2. You will be deploying on Ethereum mainnet. Some screenshots in this guide are from the deprecated Holesky testnet (use Hoodi for testing from now on) just for demonstration purposes, so please verify you are using the correct [mainnet addresses](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). + +## Getting started + +This guide is broken down into 3 parts: + +Part 1: Creating a shared [SAFE](https://safe.global/) wallet for the cluster, and a [Splits.org](https://splits.org) reward splitting contract + +Part 2: Using the [Obol DV Launchpad](https://launchpad.obol.org/) + CLI to create the cluster + +Part 3: Deploying the validator to Lido's CSM using their UI. + +:::tip +In this guide we'll be using the CSM widget and expanding `Specify Custom Addresses` to set the `Manager Address` to the cluster multi-sig (SAFE) and the `Rewards Address` to the Splits.org splitting contract. Finally, we'll be selecting `Extended` permissions type which grants `Manager Address` ultimate control over the Node Operator. +::: + +## Part 1: Creating the Cluster SAFE + Splitter Contract + +### Deploy the SAFE + +Detailed instructions on how to create a SAFE Wallet can be found [here](https://help.safe.global/en/articles/40868-creating-a-safe-on-a-web-browser). + +The squad leader should obtain signing addresses for all the cluster members, to create a new SAFE with the operators all as owners. + +![](/img/gitbook/image-28.png) + +After giving the Safe a name and selecting the appropriate network, continue by clicking the **Next** button. + +![](/img/gitbook/image-29.png) + +Add all the signer addresses of the cluster members, select a threshold, and proceed to the final step by clicking the **Next** button. + +:::info +Don't require 100% of signers to approve transactions, in case someone loses access to their address. Using the same [threshold](../../learn/intro/key-concepts.md#distributed-validator-threshold) as your cluster will use is a reasonable starting point. +::: + +![](/img/gitbook/image-30.png) + +Finally, submit the transaction to create the Safe by clicking on the **Create** button. + +![](/img/gitbook/image-31.png) + +### Deploy the Splitter Contract + +The squad leader should obtain the reward addresses from all the cluster members (this can be the same address used in the SAFE contract). Open https://app.splits.org and create a `New contract`. Make sure to select the appropriate network. + +![](/img/gitbook/image-32.png) + +Select `Split` for the contract type. + +![](/img/gitbook/image-33.png) + +Add the reward addresses of all cluster members. Choose whether the contract is immutable (recommended option), whether to sponsor the maintainers of [splits.org](https://splits.org), and optionally whether to set a distribution bounty such that third parties could pay the gas costs of distributing the accrued rewards in exchange for a small fee. + +:::tip +If your cluster would like to contribute a portion of its rewards to Obol protocol development, thereby earning [Obol Incentives](https://obol.org/incentives) as part of Lido's [integration of CSM](https://research.lido.fi/t/integrate-csm-into-the-decentralized-validator-vault/8621) into the DV Vault, you must add [protocoldevelopmentfee.obol.eth](https://etherscan.io/address/0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d) as a recipient of 0.1% of the splitter contract. This will contribute 0.1% of rewards **and your CSM bond** to Obol protocol development. Future versions of CSM integrations will enable contributing exactly 1% of accruing CSM rewards +::: + +![](/img/gitbook/image-34.png) + +Finally, click the **Create Split** button, execute the transaction and share the created split contract with all cluster members for review. + +## Part 2: Use the DV Launchpad + CLI to create the cluster keys + +`Charon` is the middleware client that enables validators to be run by a group of independent node operators - a cluster or squad. A complete multi-container `Docker` setup including execution client, consensus client, validator client, MEV-Boost, the `Charon` client and monitoring tools can be found in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node). + +### Step 1: Clone the repo + +```sh +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +``` + +### Step 2: Create ENR and Backup your Private Key + +Enter the CDVN directory: + +```sh +cd charon-distributed-validator-node +``` + +Use docker to create an ENR + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 create enr +``` + +### Back up the private key located in `.charon/charon-enr-private-key` + +![](/img/gitbook/image-35.png) + +:::warning +What you see in the console starting with `enr:-` is the **public key** for your Charon node (known as an ENR). The **private key** is in the file `.charon/charon-enr-private-key`, be sure to back it up securely. +::: + +### Step 3: Create the DV cluster configuration using the Launchpad + +Obol has integrated the CSM details into the DV Launchpad. Choosing the "Lido CSM" withdrawal configuration allows you to create validator keys with Lido's required withdrawal and fee recipient addresses. + +To start, the squad leader opens the [DV Launchpad](https://launchpad.obol.org), then connects their wallet and chooses **Create a cluster with a group**. + +![](/img/gitbook/image-36.png) + +Then click **Get Started**. + +![](/img/gitbook/image-37.png) + +Accept all the necessary advisories and sign to confirm. + +![](/img/gitbook/image-38.png) + +Cluster configuration begins next. First, select the cluster name and size, then enter all cluster members signer addresses. + +![](/img/gitbook/image-39.png) + +* Select the number of validators to create. +* (If the cluster creator is taking part in the cluster) Enter your Charon node's ENR which was generated during [step 2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. +* In the **Withdrawal Configuration** field, select `LIDO CSM`. This will automatically fill the required Withdrawal Address and Fee Recipient Addresss per [Lido's Documentation](https://operatorportal.lido.fi/modules/community-staking-module#block-d8e94f551b2e47029a54e6cedea914a7). +* Finally, click on the **Create Cluster Configuration** button. + +![](/img/gitbook/image-40.png) + +Lastly, share the cluster invite link with the other cluster members. + +![](/img/gitbook/image-41.png) + +### Step 4: Distributed Key Generation (DKG) + +All squad members need to open the cluster invitation link, connect their wallet, accept all necessary advisories, and to verify the cluster configuration is correct with a signature. Each squad member will also need to upload and sign an ENR to represent their charon client, so see [steps 1](lido-csm.md#step-1-clone-the-repo) and [2](lido-csm.md#step-2-create-enr-and-backup-your-private-key) above. + +![](/img/gitbook/image-42.png) + +Once all members confirm the configuration they will see the **Continue** button. + +![](/img/gitbook/image-43.png) + +On the next page, they will find a CLI command which is used to begin the Distributed Key Generation (DKG) ceremony. All members need to synchronously complete this step. + +![](/img/gitbook/image-44.png) + +:::tip +Go back to the terminal and make sure you're in the `charon-distributed-validator-node` directory before running the DKG command: + +```sh +pwd +``` + +If you are not, navigate to it using the `cd` command. +::: + +Paste the DKG command into your terminal and wait for all the other squad members to connect and complete the DKG ceremony. + +![](/img/gitbook/image-46.png) + +New files were generated: `cluster-lock.json`, `deposit-data.json`, `validator_keys` are all found in the `.charon` folder (hidden by default). This contains each operator's partial key signatures for the validators. + +:::danger +At this point, **each operator must make a backup of the `.charon` folder and keep it safe, as validator keys cannot be recreated if lost**. +::: + +### Step 5: Create a `.env` file for Mainnet + +Copy and rename the `.env.sample.mainnet` file to `.env` + +```sh +cp .env.sample.mainnet .env +``` + +Open the `.env` file using your favourite editor: + +```sh +nano .env +``` + +Uncomment and set `BUILDER_API_ENABLED=true`. + +Uncomment `MEVBOOST_RELAYS=` and set it to the URL of at least one of Lido's approved MEV relays [here](https://enchanted-direction-844.notion.site/6d369eb33f664487800b0dedfe32171e?v=8e5d1f1276b0493caea8a2aa1517ed65). Multiple relays must be separated by a comma. Consult our [deployment best practices](../prepare/deployment-best-practices.md#mev-boost-relays) for further info on MEV relay selection. + +### Step 6: Starting the Node + +Each cluster member should start the node with the following command: + +```sh +docker compose up -d +``` + +At this point, execution and consensus clients should start syncing. Charon and the validator client should start waiting for the consensus client to be synced and the validator to be activated. + +## Part 3: Upload the public keys and deposit to Lido CSM + +CSM V2 enables a new Operator Type called Identified Community Staker ("ICS"). The squad member who is an ICS should be the one to create the node through the CSM widget. Doing so ensures the clusters validators receive [ICS benefits](https://blog.lido.fi/unlock-exclusive-benefits-as-an-identified-community-staker/). + +ICS member heads to [csm.lido.fi](https://csm.lido.fi/) and connects their wallet. + +![](/img/gitbook/image-47.png) + +The ICS member clicks on the **Create Node Operator** button. + +![](/img/gitbook/image-48.png) + +* The ICS member pastes the contents of the `deposit-data.json` file into the `Upload deposit data` field. The ICS member should have enough ETH/stETH/wstETH to cover the bond. +* Expand the **Specify custom addresses** section. + * Set the **Reward Address** field to the `Split` contract address and the **Manager Address** field to the `Safe` wallet address. (These were created previously in [part 1](lido-csm.md#part-1-creating-the-cluster-safe--splitter-contract)) + * Verify that the **Extended** box is outlined. This ensures that the `Safe` address has the ability to change the reward address if necessary. +* Check that the correct addresses are set and click the **Create Node Operator** button. + + ![](/img/gitbook/image-49.png) + +Sign the transaction. The cluster is ready for deposit from Lido CSM. At this point, your job is finished. + +:::warning +When claiming your cluster's rewards, **be sure to claim in wstETH**. Claiming native ETH will result in loss of funds. Rebasing tokens like stETH may not receive the incremental yield you’re expecting. More information can be found in the [splits.org documentation](https://docs.splits.org/core/split#how-it-works). +::: diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-for-capital-allocators.md b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-for-capital-allocators.md new file mode 100644 index 0000000000..8a5908a93b --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-for-capital-allocators.md @@ -0,0 +1,450 @@ +--- +sidebar_label: "For Capital Allocators" +slug: /run-a-dv/integrations/lido-v3-stvault-integration-kit/lido-v3-stvault-for-capital-allocators +--- + +# For Capital Allocators + +*** + +## Quick Overview + +**Target audience:** ETH capital allocators – retail, treasuries, funds, ETF/ETP issuers, institutions. + +:::info +Obol's [Cluster-as-a-Service](https://hubs.ly/Q03Y2Srl0) offering can get you started quickly: we act as a trusted advisor, connect you with top node operators, and help guide decisions around validator sidecars and MEV strategies. +::: + +For a capital allocator, a **Lido stVault** provides a way to create a **dedicated, siloed ETH staking vault**: + +* you choose the **node operator set** (e.g. by geography, infrastructure used, reputation), +* you agree on **additional reward arrangements** (e.g. [ETH gas](https://www.ethgas.com/), [Primev](https://www.ethgas.com/), other DV compatible incentives), +* and you retain the option to tap into **stETH liquidity** at the vault level. + +That liquidity can then be used by a curator or strategy provider for things like **boosted APR via looping**, **restaking**, or other structured strategies – while the underlying validators are run by an **Obol Distributed Validator (DV) cluster** for operational resilience. + +*** + +## Definitions + +**stVaults** are Lido's staking "building blocks": isolated vaults that hold ETH, run validators, and (optionally) mint stETH under a configurable risk framework. Each vault has its own operator set and parameters, so risk and behavior are compartmentalized rather than shared across the entire protocol. + +On top of this, Obol provides **Distributed Validator Technology (DVT)**: validator keys and duties are spread across multiple independent operators/nodes rather than being concentrated on a single computer. + +### stVault terminology + +* **stVault** + + A Lido V3 vault that: + + * accepts ETH, + * funds validators on the beacon chain, and + * can optionally mint stETH under a specific tier configuration (Reserve Ratio + minting cap) for DeFi / strategy use. +* **Reserve Ratio (RR)** + + The percentage of vault value that must remain reserved as collateral when minting stETH. + + * No stETH can be minted for this reserved portion. + * Higher RR ⇒ more conservative, less minting capacity. + * Lower RR ⇒ more capital efficient, more minting capacity (within caps). +* **Tier** + + A risk configuration assigned to a Node Operator. A tier defines: + + * a **Reserve Ratio (RR)**, and + * a **maximum stETH minting cap** for vaults attached to that tier. +* **Default tier** + + The tier applied to vaults created by **non-identified** node operators: + + * fixed **RR = 50%**, + * conservative minting behavior, especially in early rollout phases. +* **DVT tiers** + + Tiers designed for vaults operated by **multi-operator DV clusters** (e.g. Obol). The current default DV vault schedule proposed in Lido's risk framework is: + + * **Tier 1** – up to 50,000 ETH used for minting capacity, **RR = 2%** → max \~49,000 stETH + * **Tier 2** – up to 50,000 ETH, **RR = 2%** → max \~49,000 stETH + * **Tier 3** – up to 200,000 ETH, **RR = 2%** → max \~196,000 stETH + * **Tier 4** – up to 300,000 ETH, **RR = 3%** → max \~291,000 stETH + * **Tier 5** – up to 400,000 ETH, **RR = 4%** → max \~384,000 stETH + + In total, these DVT tiers allow up to **969,000 stETH** to be minted on **1,000,000 ETH** of "mintable" value, reflecting higher capital efficiency than the Default 50% RR, while still enforcing explicit per-tier caps. +* **Total Value** + + The sum of: + + * ETH staked in validators (including rewards), and + * ETH held in the vault's balance. +* **stETH Liability / Minting Capacity / Utilization / Health Factor** + + Core metrics Lido uses to track vault safety and usage: + + * **stETH liability** – how much stETH the vault has minted, + * **minting capacity** – how much more could be minted given RR and caps, + * **utilization** – what fraction of capacity is in use, + * **health factor** – how safely the vault is collateralized. + +### Obol terminology + +* **Distributed Validator (DV)** + + A validator whose signing key is split across multiple operator nodes. Duties are executed collaboratively through DV middlewares (for example, Obol's Charon or Nethermind's Pluto), so no single node holds the full key or can unilaterally control the validator. +* **DVT (Distributed Validator Technology)** + + The underlying cryptographic and networking stack that makes DVs possible: threshold BLS signatures, distributed key generation, signature aggregation, peer to peer communication, and consensus components. +* **DV cluster** + + A group of independent node operators jointly running one or more DVs. + + In the Lido stVault context, DVT categories typically assume: + + * **4 or more independent operators**, and + * validator keys generated via a DKG ceremony. +* **DKG (Distributed Key Generation)** + + A protocol that generates validator private keys collaboratively such that: + + * no single operator ever knows the full validator private key, and + * key shares can be used jointly to produce valid signatures. +* **Curator / Strategy provider** + + An entity responsible for the _economic_ behavior of the vault: + + * deciding whether the vault is staking only, or using minted liquid staked tokens to generate further yield. + * designing and managing these further strategies (e.g., looping, hedging price risk, or other structured approaches). + + Obol can help connect depositors with suitable curators where an end-to-end solution is desired. + +*** + +## Comparison: Lido Core vs non-DV Vault vs Vault on Obol DVs + +| Dimension | Staking via Lido Core (no vault) | Staking with a Vault (no DV) | Staking with an Obol DV and a Vault | +| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **What it is** | Stake directly through Lido Core; ETH is pooled and allocated across Lido's curated operator set. | ETH is deposited into a **dedicated stVault** with a chosen single node operator; vault can optionally mint stETH under a tier (RR + cap). | ETH is deposited into a **dedicated stVault** whose validators are run by a **multi-operator Obol DV cluster**; vault can target DVT-specific tiers over time. | +| **Risk isolation & scope** | Risk is **global** at the protocol level; underperformance or slashing impacts the broader Lido Core pool. | Each stVault is a **siloed risk container**; failures or misconfigurations are contained to that vault, not the global pool. But failure risk is higher due to lack of diversity of operators and clients. | Same per-vault isolation as a non-DV vault, **plus** risk is mitigated due to multiple operators inside the DV cluster sharing the staking duties. | +| **Operator model** | Operators are selected by Lido and managed via governance; you do **not** choose specific operators for your stake. | You select a **specific operator** (or operator entity) per vault and rely on them for security and resilience. But even the biggest operators can be [subject to attacks](https://www.theblock.co/post/370141/kiln-exits-ethereum-validators) despite their best practices. | You select or approve a **set of independent operators** forming a DV cluster. No one holds the entire private key, protecting your stake even when an operator is compromised. | +| **Operational resilience** | Resilience comes from Lido's **diversified operator set** at protocol scale, but each validator is still run by a single operator in the majority of cases. | Validator duties are typically run on a **single operator's stack**. A misconfig, hardware failure, or outage can significantly impact that vault's uptime and rewards. | Duties are distributed across a **DV cluster** (multiple operators/machines, often across geographies). The system is not down with one node/operator going offline. | +| **Tiers & Reserve Ratio (RR)** | You don't see or control tiers directly; you simply receive stETH and its yield. | Vault uses a **tier** (RR + cap). Non-identified operator vaults default to **50% RR** (Default tier) with conservative minting behavior. | Vault can qualify for **DVT tiers**: RR as low as **2–4%** with explicit per-tier minting caps (e.g. 5 tiers totalling 1,000,000 ETH "mintable" with 969,000 max stETH). It is 10+ times better than non-identified, non-DV vaults | +| **Access to DVT tiers** | No direct access: there's no per-vault DVT tier concept since you're staking into the global Lido Core pool. | Not DVT by design, so **no DVT tier** access; can only move from Default 50% RR to other non-DVT identified tiers (if/when operator qualifies). | DV cluster can be **identified** via Lido's Identified Node Operator process and attached to **DVT tiers**, providing a path from Default 50% RR to lower-RR, higher-efficiency tiers. | +| **Capital efficiency & strategies** | stETH/wstETH is liquid and can be used in DeFi, but there is no per-vault RR control; strategies are entirely external to Lido Core. | Vault can mint stETH subject to its RR and caps; with **50% RR**, leverage for looping/restaking is limited, so APR uplift over baseline staking is modest. | Low-RR DVT tiers enable **much higher minting capacity** for the same TVL, making looping/restaking strategies more capital efficient (e.g. meaningful APR uplift vs Default RR 50%). | +| **Strategy surface (looping, etc.)** | Strategy design is off-protocol; you use stETH in external DeFi venues. | Strategies can be layered at the vault level (via a curator), but constrained by higher RR if the operator isn't DVT-qualified. | Vault becomes a **strategy-friendly substrate**: DVT tiers with low RR + health metrics + multi-op resilience make it a natural base for looping, restaking, and structured products. | +| **Governance & customization** | Governance is at the Lido protocol level; you cannot customize per-pool economics or operator sets for your specific capital. | You can customize **governance, fees, and operator choice** per vault using roles (e.g. fund-specific or ETF-specific vaults with bespoke controls). | Same per-vault governance/customization but roles can be given to a multisig-Safe wallet for extra security across operators. | +| **Typical user / use case** | Users who want **simple, liquid staking** and are comfortable with protocol-wide diversification instead of bespoke vaults. They would like to actively manage their own strategies and calculate risks associated with it. | Capital allocators wanting **dedicated infrastructure** and configurable fees/parameters, but willing to accept **single-operator slashing and downtime risks**. | Capital allocators who want **dedicated vaults**, **multi-operator resilience**, a **governed path to DVT tiers (lower RR)**, and the option to run advanced strategies on top. | + +## Understanding impact of RR with an Example + +To illustrate how DVT RR if utilized properly can yield boosted APR, we compare three cases: + +1. **No looping** (pure staking) +2. **Looping on non-DVT vault** (50% mintable capacity) +3. **Looping on DVT vault** (98% mintable capacity) + +It must be noted that following calculations are only for illustrative purpose and numbers will vary with market conditions and risk appetite. To understand the calculations, refer to the appendix. + +**High-level outcomes** + +| Case | Mintable fraction | Effective leverage (≈ TVL / capital) | Approx. TVL in vault | Approx. total borrow | User APR (net) | +| ------------------------------------ | ----------------- | ------------------------------------ | -------------------- | -------------------- | -------------- | +| No looping | 0% (no minting) | **1.0×** | 10,000 | 0 | **≈ 2.84%** | +| Looping – non-DVT vault (default RR) | 50% | **≈ 1.87×** | ≈ 18,687 | ≈ 8,687 | **≈ 3.16%** | +| Looping – DVT vault (DVT tier) | 98% | **≈ 7.22×** | ≈ 72,188 | ≈ 62,188 | **≈ 5.19%** | + +Where: + +* **Effective leverage** ≈ `Total vault value / Initial capital` +* **Total borrow** is the cumulative ETH borrowed from Aave and re-deposited into the vault. + +:::warning +Eth Staking APR and Eth borrow cost are variable. Borrowing cost can be higher than the staking APR, resulting in a negative APR from looping. Consult the appendix below for more information. +::: + +*** + +## How Should I Stake? – High-Level Decision Tree + +``` +Start + ├─→ Are you a retail user or an allocator who does NOT need a dedicated, isolated vault? + │ │ + │ ├─→ YES → Use a shared vault such as the Ethereum Client Team Vault + │ │ (pooled vault, boosted strategies, Primev rewards) + │ │ + │ └─→ NO → Continue ↓ + │ + └─→ Are you an ETF issuer, fund, DAO treasury, or institution that + requires segregation of ETH and custom governance/controls? + │ + ├─→ YES → Create a dedicated DVT stVault with Obol + │ (per-vault operators, governance, strategies) + │ + └─→ NO → Consider whether a DeFi-wrapper enabled vault already meets + your requirements; if in doubt, talk to Obol. + +``` + +*** + +## Path A: Shared DeFi-Wrapper Vault (Retail / Non-Dedicated) + +**Who this is for** + +* Retail users, DAOs, funds, or smaller treasuries that: + * don't need their **own dedicated vault**, and + * want exposure to **pooled strategies** with boosted rewards. + +**What you get** + +* A **DeFi-wrapper vault** (launching in January 2026) that: + * pools ETH from multiple users into an underlying stVault, + * is **run by Ethereum client teams** and curated by **Nethermind**, + * implements **boosted strategies** (e.g. looping, restaking), + * leverages **Primev** for additional rewards where applicable. + +**What you do** + +* Deposit ETH into the 'Ethereum Client Team Boosted Vault'. +* Receive the wrapper's token / position representing your share. +* Monitor: + * published strategy, + * net APR after fees, + * risk disclosures (health/LTV-style metrics where available). + +You **do not** need to handle: + +* vault creation, +* node operator selection, +* Obol DV cluster formation. + +All of that is handled by the client teams + Nethermind (strategy), with Obol DVT under the hood. + +*** + +## Path B: Dedicated DVT stVault with Obol (ETF / Treasury / Institutional) + +If you are an ETF issuer, large fund, DAO treasury, or any allocator that **does not want to pool ETH with other users** or have specific choice of operators, you will create a **dedicated DV stVault**. + +Obol will assist along the way: from design → DV cluster → identification → strategy. + +### Step 1 — Define the Vault and Its Controls + +**Who this is for** + +* Capital allocators that require: + * **segregated ETH**, + * specific governance (e.g. ETF board / DAO / foundation), + * audit-friendly parameterization (fees, roles, permissions). + +**Decisions you make** + +* **Product scope** + * _Staking-only_, or + * _Staking + optional liquidity/strategies_ (e.g. looping, restaking, Primev, etc.). +* **RR / tier posture** + * Start at **Default 50% RR** (non-identified), with a plan to move to DVT tiers later, or + * Aim directly for DVT tiers via early alignment with Lido's DVT category. +* **Governance model** + * Multisig composition for: + * vault owner / governance safe, + * node operator safe, + * fee recipient / accounting. + * Emergency powers (pauses, exits). + * Fee parameters (node operator fee, any additional service/strategy fees). + +**What happens technically** + +* A **stVault** is deployed with: + * roles and permissions matching the above, + * a designated Node Operator entity (which will represent the DV cluster), + * initial tier attachment (typically defaults to 50% RR at launch). + +**How Obol helps** + +* Co-design of roles, safes, and failure modes. +* Helps you move from normal tier to a DVT tier through [Lido's identification process](https://docs.lido.fi/run-on-lido/stvaults/node-operators-identification/). +* Templates / examples for: + * governance policies, + * incident playbooks, + * fee configurations. +* Introduction to **curators / strategy providers** if you want an economic layer on top (beyond pure staking). + +:::info +For detailed identification process steps, see the [Node Operator Guide](lido-v3-stvault-for-node-operator.md#51-dv-cluster-identification-process). +::: + +*** + +### Step 2 — Assemble the DV Operators + +**Objective** + +Build a **DV cluster** that can qualify for Lido's **DVT category** and DVT tiers, while meeting your internal constraints (jurisdiction, infra diversity, etc.). + +**Requirements (high-level)** + +* **≥ 4 independent operators** (distinct entities). +* Validators run as **DVs**, not single-operator keys. +* Validator keys generated via **DKG**, so no single party ever sees the full key. +* Operational standards: + * monitoring, + * upgrade processes, + * on-call / incident response, + * SLAs. + +**What happens technically** + +* Candidate operators are selected and agree on operational expectations. +* An **Obol DV cluster** is created: + * DKG ceremony for validator keys, + * cluster configuration (Charon, clients, networking), + * metrics and alerting wired up. +* The DV cluster's structure and operational procedures are documented as part of the material needed for **Lido's Identified Node Operator process** (to attach DVT tiers later). + +**How Obol helps** + +* Maintains an ecosystem view of potential operators. +* Proposes **operator sets** that match: + * geography / jurisdiction preferences, + * infrastructure diversity (cloud vs bare metal, client diversity, etc.). +* Coordinates: + * DKG, + * cluster bootstrapping, + * best practices on monitoring and upgrades. +* Prepares technical input for the **Identified Node Operator** submission (DVT category). + +For detailed steps on the identification process, see the [Node Operator Guide](lido-v3-stvault-for-node-operator.md#51-dv-cluster-identification-process). + +*** + +### Step 3 — Strategies and Additional Rewards (Optional) + +This step is optional and only applies if you want more than the **baseline staking yield**. + +**Decisions you make** + +* Whether to: + * keep the vault **staking-only**, or + * allow **minted stETH** to be used in strategies (looping, hedged positions, restaking, Primev, etc.). +* Your comfort with: + * leverage/looping levels, + * borrow rate risk, + * extra smart contract and integration risk. + +**What happens technically** + +* A **curator / strategy provider** designs a strategy that: + * respects the vault's RR and DVT tier caps, + * stays within safe **health / utilization** bounds, + * integrates any sidecars (e.g. Primev) for extra rewards. +* The strategy is executed at the vault level: + * minting stETH (within capacity), + * routing it into external protocols, + * managing rebalances and unwinds. +* Health metrics (utilization, health factor) are monitored; corrective actions are defined in advance. + +**How Obol helps** + +* Connects you with **curators** who have relevant experience (looping, restaking, market-neutral, etc.). +* Provides **operational constraints** from the validator side: + * how often it is safe to rebalance without stressing infra, + * how exits/redemptions map to validator exit queues. +* Works alongside the curator to ensure the strategy is compatible with: + * cluster operations, + * Lido's risk framework, + * your internal risk policies. + +## Appendix + +### Parameters Used + +| Category | Parameter | Value | +| ----------------- | --------------------------- | --------------------------- | +| User | Initial capital | **10,000** | +| stVault economics | stVault gross yield | **3.15%** | +| | Node operator fee | **2.0%** (of staking yield) | +| | Obol fee | **0.5%** (of staking yield) | +| Lido fees | Lido infra fee | **1.0%** (of staking yield) | +| | Lido liquidity fee | **6.5%** (of staking yield) | +| | Total fee share | **10.0%** of staking yield | +| | **Net base APR to user** | **≈ 2.84%** (no looping) | +| stETH reference | stETH gross yield | **3.0%** (context only) | +| Vault tier | Mintable capacity (DVT) | **98%** of vault value | +| | Mintable capacity (non-DVT) | **50%** of vault value | +| Aave / looping | Loops | **10** | +| | wstETH LTV | **93%** | +| | wstETH supply APY | **0.04%** | +| | ETH borrow cost | **2.5%** | + +For the example we compress all staking-side fees into a single **net base yield**: + +``` +stVault gross yield = 3.15% +Total fee share on yield = 1.0% + 6.5% + 2.0% + 0.5% = 10.0% + +Net base APR to user (no looping) +r_base_net = 3.15% × (1 − 10%) ≈ 2.835% + +``` + +So with _no looping_, a 10,000 deposit would earn ≈ 2.84% APR. + +*** + +### How the APR Is Calculated (Conceptual) + +For each case with looping we approximate: + +``` +Profit ≈ TV × r_base_net + minted_stETH × r_supply − borrowed_ETH × r_borrow + (staking on TV) (Aave supply APY) (borrow cost) + +User APR ≈ Profit / Initial capital + +``` + +Using: + +* `r_base_net ≈ 2.835%` (net staking APR to user, from the stVault) +* `r_supply = 0.04%` (wstETH supply APY on Aave) +* `r_borrow = 2.5%` (ETH borrow cost) + +### Case B – Non-DVT vault (50% mintable) + +After 10 loops: + +* `TV ≈ 18,687` +* `minted_stETH ≈ 9,341` +* `borrowed_ETH ≈ 8,687` + +Approximate annual profit: + +* Base staking: `18,687 × 2.835% ≈ 530` +* Aave supply: `9,341 × 0.04% ≈ 3.7` +* Borrow cost: `8,687 × 2.5% ≈ 217` + +``` +Profit ≈ 530 + 3.7 − 217 ≈ 316 +APR_default ≈ 316 / 10,000 ≈ 3.16% + +``` + +### Case C – DVT vault (98% mintable) + +After 10 loops: + +* `TV ≈ 72,188` +* `minted_stETH ≈ 66,869` +* `borrowed_ETH ≈ 62,188` + +Approximate annual profit: + +* Base staking: `72,188 × 2.835% ≈ 2,046` +* Aave supply: `66,869 × 0.04% ≈ 26.7` +* Borrow cost: `62,188 × 2.5% ≈ 1,555` + +``` +Profit ≈ 2,046 + 26.7 − 1,555 ≈ 518.6 +APR_DVT ≈ 518.6 / 10,000 ≈ 5.19% + +``` diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-for-node-operator.md b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-for-node-operator.md new file mode 100644 index 0000000000..aac28a2fea --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-for-node-operator.md @@ -0,0 +1,488 @@ +--- +sidebar_label: "For Node Operators" +slug: /run-a-dv/integrations/lido-v3-stvault-integration-kit/lido-v3-stvault-for-node-operator +--- + +# For Node Operators + +:::info +**Scope:** This guide is for node operators who operate a **Lido V3 stVault** with an **Obol Distributed Validator (DV) cluster**. + +It assumes: + +* stVault creation is done via **Lido's stVault UI** or **Lido's stVault CLI**, and +* validator operations (deposit, exit, withdrawal, etc.) are performed using **Lido stVault CLI or Lido's stVault UI** only. + +Reserve ratio benefits require **multi-operator DV vaults**. Single-operator setups do not qualify you for improved reserve ratios (though may qualify you for Obol's [Incentive](https://obol.org/incentives) program). +::: + +*** + +## 1. High-Level Flow (Multi-Operator Obol DV Vaults) + +At a high level, the lifecycle for a multi-operator Obol DV stVault is: + +1. **Create the stVault** + + – via **Lido stVault UI** (recommended where available) or **Lido stVault CLI**. +2. **Set up governance & fee routing** + + – Configure a `GOVERNANCE_SAFE` and `NODE_OPERATOR_SAFE` using Gnosis's [Safe UI](https://app.safe.global/) as well as a `FEE_SPLIT_CONTRACT` using the [splits.org](http://splits.org) UI. +3. **Create and publish the Obol DV cluster** + + – Use the `charon create dkg --publish` command or the [DV Launchpad](https://launchpad.obol.org/) to create a multi-operator DV cluster with the vault as both the withdrawal and fee recipient addresses. Use the `--operator-addresses` flag to invite the Node Operators to complete the DKG ceremony. +4. **Run and monitor the DV cluster** + + – using Obol’s observability stack. +5. **Monitor the vault** + + – using **Lido stVault CLI** (`contracts dashboard` and `vo` read commands) plus the stVault UI. +6. **Distribute rewards and fees** + + – from the vault to the split contract, and from the split contract to participants (including Obol). + +*** + +## 2. Creating the Vault (UI vs CLI) + +You can create a stVault in two ways: + +* **Lido stVault UI (recommended)** + * Hoodi testnet UI: `https://stvaults-hoodi.testnet.fi/` + * Mainnet stVault UI link will follow Lido’s official docs once live. +* **Lido stVault CLI** + * Main docs and command reference: + + `https://lidofinance.github.io/lido-staking-vault-cli/` + +The CLI exposes two main entry points you will use: + +* `vo` – **vault-oriented commands** (lower-level, contract-centric). +* `contracts dashboard` – **dashboard-oriented commands** (product/UX layer, usually nicer for day-to-day). + +**Practical split:** + +* Use **`contracts dashboard r overview / health / info` as your primary monitoring entrypoint** (per vault “product”). +* Use **`vo r overview / health / info / roles`** when you need contract-level detail, addresses, or role debugging. + +:::warning +For beacon-chain deposits, validator exits, withdrawals and other stVault operations, use the Lido stVault UI or Lido stVault CLI only. + +Do **not** use the Obol Launchpad UI for these validators. +::: + +For the rest of this guide we assume a **multi-operator DV vault** with, for example: + +* **Cluster size:** 4 operators +* **Cluster limit:** up to \~1,000,000 ETH (subject to Lido risk / tier approvals) +* **Validator max stake:** 1,920 ETH per validator (allowing space for compounding) +* **Total validators:** \~520–600 in a full configuration + +These values are **illustrative**; actual limits depend on your and your depositor’s risk framework and governance. + +*** + +## 3. Core On-Chain Addresses & Safes + +Before (or alongside) vault creation, set up three core components. + +### 3.1 Governance Safe (`GOVERNANCE_SAFE`) + +* **Role:** vault owner / governance multi-sig. +* **Where to create:** + * Mainnet: `https://safe.global/` + * Hoodi testnet: Protofire Safe UI – `https://app.safe.protofire.io/` +* **Example policy:** + * 3/4 multi-sig across: + * client / treasury signers and/or + * operator representatives. + * Typically used as: + * **Vault Owner** + * **Default Admin / Node Operator Manager** + +*** + +### 3.2 Node Operator Safe (`NODE_OPERATOR_SAFE`) + +* **Role:** operational multi-sig for day-to-day validator + vault actions. +* **Where to create:** + * Mainnet: `https://safe.global/` + * Hoodi: `https://app.safe.protofire.io/` +* **Example policy:** + * 3/4 multi-sig across node operators and/or client infra. +* **Typical responsibilities:** + * Funding the vault + * Depositing to beacon chain + * Requesting validator exits + * Triggering withdrawals + * Initiating rebalances + * Minting/burning stETH if allowed by governance + * Interacting with Lido stVault contracts via CLI + +*** + +### 3.3 Fee Split Contract (`FEE_SPLIT_CONTRACT`) + +On **mainnet**, Obol’s protocol fee is enforced via a fee splitting contract: + +* Create via the **Splits.org UI**: `https://app.splits.org/` +* Configure: + * **1% of validator rewards → Obol protocol fee address** + + `0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d` + * Remaining percentage split between operators according to your commercial terms. + +On **Hoodi**, Splits may not be available or may not support that network: + +* You may **skip the split contract** on testnet. +* On mainnet, **using a split contract that routes 1% of validator rewards to Obol is required** to earn Obol's incentive rewards. If this vault will be extremely significant, consider reaching out to the Obol core team to discuss the potential for a custom arrangement. + +The image below shows using the splits UI to create a split contract where 5% of validator rewards will be distributed equally across the 4 node operators and Obol. + +![](/img/gitbook/SPLITS-UI-RECIPIENTS.png) +
Example split contract configuration
+ +:::info +Consider setting the controller for this split contract to `NODE_OPERATOR_SAFE` or `GOVERNANCE_SAFE` to retain the ability to modify it at a later date. +::: + +*** + +## 4. Recommended Vault Parameters & Roles + +When creating the vault via UI or CLI, we recommend the following mapping. + +### 4.1 Main Settings (Vault Parameters) + +* **Node Operator:** `NODE_OPERATOR_SAFE` + + Entity responsible for validator operations and day-to-day vault actions. +* **Vault Owner:** `GOVERNANCE_SAFE` + + Controls vault ownership, high-level parameters, and emergency controls. +* **Node Operator Manager:** `GOVERNANCE_SAFE` + + Oversees the Node Operator; can be a separate address if required by governance. +* **Node Operator Fee Recipient:** `FEE_SPLIT_CONTRACT` + + Set **after vault creation** so all node-operator fees route through the splitter. +* **Node Operator Fee:** typically **3–10%** (expressed in basis points in the UI / CLI). +* **Confirmation Lifetime:** e.g. **48 hours** + + Relevant if `Vault Owner` and `Node Operator Manager` differ; defines how long confirmations are valid for sensitive operations. + +For the latest flags and options when creating a vault, refer to: + +**Lido stVault CLI – `vo` commands** + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations` + +*** + +### 4.2 Role Assignments & Responsibilities (Recommended) + +| Address | Type | Permissions (examples) | Duties (examples) | Notes | +| -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `GOVERNANCE_SAFE` | Multi-sig (e.g. 4/5) | Grant / revoke roles, transfer vault ownership, set confirmation expiry, pause / resume deposits, recover stuck assets, change node operator, set fee rates. | Strategic governance, emergency handling, fee structure oversight, monitoring node-operator performance, asset recovery. | Primary governance. Often also the node operator manager and vault owner. | +| `NODE_OPERATOR_SAFE` | Multi-sig (e.g. 3/4) | Deposit ETH to beacon chain, manage validator operations, trigger withdrawals, request exits, rebalance vault, monitor performance, claim node-operator fees. | Day-to-day vault and validator operations, responding to alerts, maintaining uptime and SLAs. | Single operational entry-point; should follow strict runbooks and operational policies. | +| `FEE_SPLIT_CONTRACT` | Smart contract | Anyone can call **distribute** to disburse the funds. | Receive node-operator fee rewards, splits across participants. | Obol gets 1% fee share via its protocol address; or as per commercial agreement. | + +These are **recommendations**, not stVault requirements; adapt to your own governance needs and risk appetite. + +*** + +## 5. Obol DV Cluster Setup (Multi-Operator Only) + +After the vault and core addresses exist, you can set up the **Obol DV cluster**. + +Follow Obol’s docs for **multi-operator DV setup**: + +* **Cluster size:** minimum 4 independent operators recommended +* **Compounding validators:** `true` (recommended for vault integrations). +* **Withdrawal address:** vault withdrawal address. +* **Fee recipient address:** vault / dashboard address. +* **Number of validators:** sized to your capacity and Lido-approved tier. + +Obol cluster creation docs: + +[Create a DV With a Group](../start/create-a-dv-with-a-group.mdx) + +:::info +When generating the cluster lock, use the --publish flag so the cluster lock is published and verifiable by: + +* DV participants, +* Lido risk review & DV tier evaluation, and for +* Better support by the Obol Team in troubleshooting cluster issues. +::: + +![](/img/gitbook/LIDO-STVAULT-OVERVIEW.png) + +![](/img/gitbook/CUSTOM-WITHDRAWAL-CONFIG.png) + +### 5.1 DV Cluster Identification Process + +After creating and publishing your Obol DV cluster, you must go through **Lido's identification process** to be classified as an **Obol DV cluster** and qualify for DV-specific tiers with improved Reserve Ratio (RR) and stETH minting limits. + +**Why identification matters:** + +* **Unidentified clusters** default to the **Default tier** with only a **50% Reserve Ratio** and limited stETH minting capacity. +* **Identified DV clusters** can qualify for **DV tiers** with **Reserve Ratios as low as 2-4%** and significantly higher stETH minting limits. + +For detailed tier breakdowns and capital efficiency benefits, see the [Capital Allocator Guide](lido-v3-stvault-for-capital-allocators.md#stvault-terminology). + +**The identification process:** + +1. Each individual Node Operator in the cluster must complete the identification process (post on Lido Research Forum, complete identification forms). +2. A cluster representative posts a **DV Cluster identification request** on the Lido Research Forum. +3. The representative completes the **DV Cluster Questionnaire** with technical and business information. +4. The stVaults Committee assesses your cluster and assigns a **category and tier grid**. +5. Once identified, your cluster can access DV-specific tiers with improved economics. + +**How Obol can help:** + +* Obol provides guidance and support throughout the identification process. +* We can help coordinate the cluster identification request and questionnaire completion. +* We assist with technical documentation and cluster structure details required for the assessment. + +For detailed information about the identification process, requirements, and tier structures, refer to [Lido's Node Operators Identification documentation](https://docs.lido.fi/run-on-lido/stvaults/node-operators-identification). + +*** + +## 6. Monitoring (DV Cluster & Vault) + +### 6.1 Obol DV Monitoring + +For DV-specific monitoring (RAVER, attestations, client health, etc.), use Obol’s monitoring stack: + +Obol monitoring docs: [Monitoring Your Own Node](../running/monitoring.md), [Sending metrics to Obol](../start/obol-monitoring.mdx) + +Typical components: + +* Metrics (e.g. Prometheus) for: + * attestation success + * proposer success + * Charon peer connectivity + * execution and consensus client health +* Alerts for: + * missed duties + * insufficient peers + * clients offline + * RAVER dropping below your target (e.g. 98%, if that’s your internal standard) + +Operators should agree on: + +* shared alert channels (Slack / Telegram / Discord), and +* explicit SLAs (who responds, how quickly, escalation path). + +*** + +### 6.2 Vault Monitoring (Using Lido stVault CLI) + +The **Lido stVault CLI** exposes read-only commands that are essential for operators and vault managers. + +CLI docs root: + +`https://lidofinance.github.io/lido-staking-vault-cli/` + +You will typically use: + +* **`contracts dashboard` read commands** for primary monitoring, and +* **`vo` read commands** for lower-level details and role inspection. + +### 6.2.1 Dashboard-Centric View (Recommended UX) + +For everyday operations, prefer the **dashboard** read commands: + +```bash +# Dashboard overview +yarn start contracts dashboard r overview + +# Dashboard health +yarn start contracts dashboard r health + +# Dashboard info (addresses, parameters, vault bindings) +yarn start contracts dashboard r info + +``` + +These provide a product-level view of: + +* vault health & status +* key parameters and addresses +* high-level metrics relevant to the specific “vault product” + +Docs: + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard` + +*** + +### 6.2.2 Vault-Level View (`vo` – Advanced / Low-Level) + +For underlying vault configuration and debugging, use `vo`: + +```bash +# Vault overview (contract-level) +yarn start vo r overview -v + +# Quick health check +yarn start vo r health -v + +# Roles and permissions +yarn start vo r roles -v + +# Core vault info (fee parameters, limits, addresses, etc.) +yarn start vo r info -v + +``` + +Docs: + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations` + +In practice: + +* **Dashboard commands** → main UX surface for operators. +* **`vo` commands** → used when you need full contract detail or to diagnose odd behavior. + +*** + +### 6.2.3 Performance Metrics (`metrics` namespace) + +Use the `metrics` namespace for APR and rewards analysis: + +```bash +# Comprehensive statistics (APR & rewards) +yarn start metrics r statistic + +# APR history (simplified text mode) +yarn start metrics r charts-apr --simplified + +# Rewards distribution charts +yarn start metrics r charts-rewards + +``` + +Docs: + +`https://lidofinance.github.io/lido-staking-vault-cli/commands/metrics` + +Use these for: + +* performance reviews +* sanity-checking expected vs realized APR +* understanding the effect of DV tiers and any strategy layer + +*** + +### 6.3 Example Alerting Rules (Non-Canonical) + +:::info +The thresholds below are illustrative only. + +They are not official Lido nor Obol requirements and should be tuned to your vault's risk profile, product design, and the latest protocol guidance. +::: + +Examples of vault-level alerts you might configure: + +* **Health factor approaching 100%** + * Trigger an alert when health factor trends down into a “warning band” you define (for example, somewhere below x% according to your strategy), so you have time to respond before it reaches unsafe levels. +* **High utilization of mint capacity** + * Alert when utilization ratio is close to full (for example, above your internal high-water mark), indicating the vault is near its minting / leverage limit. +* **Low immediate liquidity** + * Alert when “available to withdraw” ETH falls below an internal buffer — for instance, less than one or two validators’ worth of ETH, depending on how your product handles withdrawals. +* **Sustained underperformance vs expectation** + * Alert when net staking APR stays materially below your internal target range for multiple reporting periods (e.g. several `metrics r statistic` runs in a row). +* **Low operational efficiency** + * Alert when net APR / gross APR (efficiency) drops below your chosen target, signalling that penalties, slashing, or high costs are eroding returns more than expected. + +**Cadence (example only):** + +* Health & dashboard checks: **at least daily**, ideally via automated alerts. +* Performance statistics (`metrics r statistic`): **weekly**. +* APR / rewards charts (`metrics r charts-apr / charts-rewards`): **monthly or quarterly** reviews. + +*** + +## 7. Deposits, Exits, Withdrawals (Pointers Only) + +This guide intentionally **does not duplicate** the full stVault operations surface. For: + +* **Beacon-chain deposits** (funding validators), +* **Validator exits**, +* **Triggering withdrawals**, +* **Withdrawing ETH from the vault to treasury**, +* **Minting / burning stETH or wstETH**, + +use the **Lido stVault CLI** docs: + +* Dashboard write commands (deposits, exits, etc.): + + [`https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write`](https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write) +* Vault / VaultHub / additional commands: + + [`https://lidofinance.github.io/lido-staking-vault-cli/category/commands/`](https://lidofinance.github.io/lido-staking-vault-cli/category/commands/) + +This keeps your operational runbooks aligned with the latest Lido contracts and CLI behaviour. + +*** + +## 8. Fees, Splits & Obol Incentives + +### 8.1 From Vault to Fee Splitter + +Step 1: disburse **node operator fees** from the vault/dashboard to `FEE_SPLIT_CONTRACT` using the Lido CLI. + +1. (Optional) Inspect vault info: + + ```bash + yarn start vo r info -v + ``` +2. Disburse node-operator fees to the configured `feeRecipient` (your splitter) using the **dashboard write** command: + + ```bash + yarn start contracts dashboard w disburse-node-operator-fee \ + + ``` + +Dashboard write docs: + +[`https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write`](https://lidofinance.github.io/lido-staking-vault-cli/commands/contracts/dashboard#write) + +This moves accrued node-operator fees from the vault to your `FEE_SPLIT_CONTRACT`. + +Hoodi link: https://stvaults-hoodi.testnet.fi/vaults/your\_vault\_address/claim + +*** + +### 8.2 From Splitter to Participants + +Step 2: **distribute and claim** via Splits.org: + +1. Open the **Splits.org UI**: [`https://app.splits.org/`](https://app.splits.org/) +2. Navigate to the page for your `FEE_SPLIT_CONTRACT` address. +3. Connect your wallet and choose either to: + * **Distribute** – moves the contract’s balance into recipients’ claimable balances. + * **Distribute and Withdraw** – moves the contract's balance into each participant's own address or Safe. Skipping their requirement to claim. + +Hoodi Link: Not available Mainnet Link: `https://app.splits.org/accounts/` + +*** + +### 8.3 Obol Rewards (Protocol Incentives) + +If the split contract is configured correctly with Obol’s share of validator rewards, **Obol incentives** can be claimed proportionally via the [Obol DV Launchpad](https://launchpad.obol.org/) by the other addresses in the split: + +Process: + +1. Connect the **recipient wallet / Safe** that's entitled to the reward on the [DV Launchpad](https://launchpad.obol.org/). +2. Click the "Dashboard" button. +3. Claim any available Obol incentives. + +:::info +The DV Launchpad can also be used by Operators to claim their outstanding wstEth rewards once someone has distributed them from the split contract to make them claimable. +::: + +Hoodi Link: [https://hoodi.launchpad.obol.org/cluster/list/](https://hoodi.launchpad.obol.org/cluster/list/) + +Mainnet Link: [https://launchpad.obol.org/cluster/list/](https://launchpad.obol.org/cluster/list/) diff --git a/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-integration-kit.md b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-integration-kit.md new file mode 100644 index 0000000000..a4e2020033 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/integrations/lido-v3-stvault-integration-kit.md @@ -0,0 +1,107 @@ +--- +sidebar_label: "Create a Lido stVault" +slug: /run-a-dv/integrations/lido-v3-stvault-integration-kit +--- + +# Create a Lido stVault + +:::info +💡 + +Lido V3 introduces **stVaults** — customizable staking vaults that unlock stETH liquidity for institutional stakers and asset managers. **Obol Distributed Validators offer the most capital-efficient way to deploy an stVault**, unlocking the **highest minting capacity** and the end game staking configuration. +::: + +## Create a Lido stVault + +**Target audience:** Node operators and capital allocators looking to deploy stVaults with **maximum capital efficiency** and institutional-grade security. + +:::info +**I'm a Node Operator**\ +Show me how to implement a DV-backed stVault.\ +[Open the Node Operator Guide](lido-v3-stvault-for-node-operator.md) +::: +:::info +**I'm a Capital Allocator**\ +Why should I use DV as infrastructure for my stVault.\ +[Open the Capital Allocator Guide](lido-v3-stvault-for-capital-allocators.md) +::: +:::info +**I Want Help from Obol**\ +[Connect with the Obol team](mailto:lido@obol.tech) or explore our [Cluster-as-a-Service](https://hubs.ly/Q03Y2Srl0) offering.
+::: +### Who This Kit Is For + +**Node operators** who are: + +* Being asked to **deploy, and operate** an stVault for a fund, DAO, protocol, or other allocator +* Building that vault on top of a **multi-operator Obol DV** rather than a single operator / single client setup + +**Capital allocators** who: + +* Need to understand **why** a DV-backed stVault can support more favorable risk assessments and reserve ratios +* Want a clear checklist for vetting operators and understanding what strong DV cluster operations look like + +### Why Obol DVs Are the Best Way to Deploy an stVault + +Lido V3's stVault design unlocks new levels of **capital efficiency** for node operators and institutional stakers. Obol Distributed Validators are **the most capital-efficient way to run a vault on Lido V3**. + +One of Lido V3's key innovations is the **Reserve Ratio (RR)**, which determines how much ETH must be kept as a reserve buffer relative to minted stETH. Lido is proposing a **2% Reserve Ratio tier for verified multi-operator DV vaults**, allowing up to **98% stETH minting capacity**. This is the most favorable tier. By comparison, the next-highest default tier for identified operators proposes a 5% RR with only 95% minting capacity. + +**Obol Distributed Validators unlock the highest minting capacity available on Lido V3.** + +#### Key Benefits + +* **Unlock the highest capital efficiency**\ + Multi-operator DV vaults qualify for the 2% Reserve Ratio tier, offering 98% stETH minting capacity, the most capital-efficient configuration on Lido V3. +* **Distribute responsibility across multiple operators**\ + Reduce reliance on any single infrastructure provider, company, or jurisdiction. Multi-operator setups distribute private key shares across many entities. +* **Maximize client and implementation diversity**\ + Run multiple consensus and execution client combinations inside the same vault, strengthening the vault's resilience and reducing correlation risks. +* **Superior liveness and fault tolerance**\ + Obol's fault-tolerant infrastructure means your validators keep performing even if individual operators experience downtime or failures. +* **Enterprise-grade security**\ + Leverage best-in-class security that institutional stakers and asset managers require for managing significant stake. + +### 📚 How This Integration Kit Is Organized + +**For Node Operators – Implementation Guide** + +A practical guide to designing, deploying, and operating an stVault using Obol DVs, including: + +* What to collect from the vault owner +* How to design your DV cluster (operators, clients, geos) +* How to rehearse on testnet and prepare for mainnet launch +* How this integrates into the Lido V3 stVault flow + +👉 [**Read the Node Operator Guide →**](lido-v3-stvault-for-node-operator.md) +**For Capital Allocators – Design & Risk Overview** + +A higher-level walkthrough of: + +* What you are optimizing for (safety, yield, minting capacity, counterparty risk) +* Why multi-operator DVs are different from "just another node operator" +* How Obol's [**Cluster-as-a-Service**](https://hubs.ly/Q03Y2Srl0) offering can help guide your decisions +* What to ask from your operators or from Obol directly + +👉 [**Read the Capital Allocator Guide →**](lido-v3-stvault-for-capital-allocators.md) +**Support & Services for stVault Builders** + +How to: + +* [Get in touch with the Obol team](mailto:lido@obol.tech) for guidance and design help +* Leverage Obol's [**Cluster-as-a-Service**](https://hubs.ly/Q03Y2Srl0) offering to get set up +### 🔗 Quick Links + +* [**Default risk assessment framework**](https://research.lido.fi/t/default-risk-assessment-framework-and-fees-parameters-for-lido-v3-stvaults/10504) — Explore how Tiers within Identified Node Operators effect the reserve ratio of the vault +* [**DV Cluster identification and assessment**](https://docs.lido.fi/run-on-lido/stvaults/node-operators-identification/#dvt-cluster-identification-and-assessment) — See the identification requirements for each node operator in a cluster in order to qualify for improved Tiering +* [**stVaults Doc Center**](https://docs.lido.fi/run-on-lido/stvaults/) — View Lido's comprehensive guides which detail how to create any product powered by stVaults + +#### Future Extensions + +As Lido's [**DeFi wrapper**](https://hackmd.io/@lido/lido-v3-wrapper-design) and more advanced strategies roll out, we will extend this kit with: + +* End-to-end reference architectures that combine stVaults, wrappers, and multi-operator DV clusters +* Config and deployment examples taken from real-world vaults +* Case studies, including the "Ethereum client team vault", once it is live + +**For now, this page gives you the map. The linked sections show you how to actually build and run the vaults behind it.** diff --git a/versioned_docs/version-v1.9/run-a-dv/prepare/README.md b/versioned_docs/version-v1.9/run-a-dv/prepare/README.md new file mode 100644 index 0000000000..a4d3971909 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/prepare/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Prepare to Run a DV" +slug: /run-a-dv/prepare +--- + +# Prepare to Run a DV + diff --git a/versioned_docs/version-v1.9/run-a-dv/prepare/deployment-best-practices.md b/versioned_docs/version-v1.9/run-a-dv/prepare/deployment-best-practices.md new file mode 100644 index 0000000000..7168c7d6e1 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/prepare/deployment-best-practices.md @@ -0,0 +1,117 @@ +--- +description: "DV Deployment best practices, for running an optimal Distributed Validator setup at scale." +sidebar_label: "Deployment Best Practices" +slug: /run-a-dv/prepare/deployment-best-practices +--- + +# Deployment Best Practices + +The following are a selection of best practices for deploying Distributed Validator Clusters at scale on mainnet. + +## Hardware Specifications + +The following specifications are recommended for bare metal machines for clusters intending to run a significant number of mainnet validators: + +### Minimum Specs + +* A CPU with 4+ cores, favouring high clock speed over more cores. ( >3.0GHz and higher or a cpubenchmark [single thread](https://www.cpubenchmark.net/singleThread.html) score of >2,500) +* 16GB of RAM +* 2TB+ free SSD disk space (for mainnet) +* 1000 read/write SSD IOPS +* 500MB/s read/write SSD speed +* 10Mbps internet bandwidth + +### Recommended Specs for extremely large clusters + +* A CPU with 8+ physical cores, with clock speeds >3.5Ghz +* 32GB+ RAM (depending on the EL+CL clients) +* 4TB+ NVMe storage +* 2000 read/write SSD IOPS +* 1000MB/s read/write SSD speed +* 25Mbps internet bandwidth + +An NVMe storage device is **highly recommended for optimal performance**, offering nearly 10x more random read/writes per second than a standard SSD. + +Inadequate hardware (low-performance virtualized servers and/or slow HDD storage) has been observed to hinder performance, indicating the necessity of provisioning adequate resources. **CPU clock speed and Disk throughput+latency are the most important factors for running a performant validator.** + +Note that the Charon client itself takes less than 1GB of RAM and minimal CPU load. In order to optimise both performance and cost-effectiveness, it is recommended to prioritise physical over virtualised setups. Such configurations typically offer greater performance and minimise overhead associated with virtualisation, contributing to improved efficiency and reliability. + +When constructing a DV cluster, it is important to be conscious of whether a cluster runs across cloud providers or stays within a single provider's private networking. This likely can impact the bandwidth and latency of the connections between nodes, as well as the egress costs of the cluster (Charon has a relatively low communication with its peers, averaging 10s of kb/s in large mainnet clusters). Ideally, bare metal machines in different locations within the same continent and with at least two providers, balances redundancy and performance. + +## Intra-cluster Latency + +It is recommended to **keep peer ping latency below 235 milliseconds for all peers in a cluster**. Charon should report a consensus duration averaging under 1 second through its prometheus metric `core_consensus_duration_seconds_bucket` and associated grafana panel titled "Consensus Duration". + +In cases where latencies exceed these thresholds, efforts should be made to reduce the physical distance between nodes or optimise Internet Service Provider (ISP) settings accordingly. Ensure all nodes are connecting to one another directly rather than through a relay. + +For high-scale, performance deployments; inter-peer latency of < 25ms is optimal, along with an average consensus duration under 100ms. + +## Peer Connections + +Charon clients can establish connections with one another in two ways: either through a third publicly accessible server known as [a relay](../../learn/charon/charon-cli-reference.md#host-a-relay) or directly with one another if they can establish a connection. The former is known as a relay connection and the latter is known as a direct connection. + +It is important that all nodes in a cluster be directly connected to one another - this can halve the latency between them and reduces bandwidth constraints significantly. Opening Charon’s p2p port (the default is `3610`) to the Internet, or configuring your routers NAT gateway to permit connections to your Charon client, are what are required to facilitate a direct connection between clients. Confirm direct peer reachability with `charon alpha test peers`. + +## Node Locations + +For optimal performance and high availability, it is recommended to provision machines or virtual machines (VMs) within the same continent. This practice helps minimise potential latency issues ensuring efficient communication and responsiveness. Consider maps of [undersea internet cables](https://www.submarinecablemap.com/) when selecting locations across oceans with low latency. + +When operating multiple nodes within a cloud environment, care must be taken to distribute nodes across availability zones to avoid AZ outages becoming cluster outages. + +## Instance Independence + +Each node in the cluster should have its own independent beacon node (EL+CL) and validator client as well as Charon client. Sharing beacon nodes between the different nodes significantly hinders the benefits of running a Charon cluster by reintroducing a single point of failure to the distributed architecture. + +## Beacon Node Redundancy + +In cases where multiple beacon nodes are available to a node, Charon should be configured to use both in parallel by adding them to `--beacon-node-endpoints`. This will query each beacon node and use the fastest response, improving both performance and availability. Only in situations where this is not economically feasible should `--fallback-beacon-node-endpoints` be used instead, which will query beacon nodes sequentially. Sequential querying will decrease performance due to timeouts being required before failover. + +## Placement of Charon clients + +If you wish to divide a Distributed Validator node across multiple physical or virtual machines; locate the Charon client on the EL/CL machine instead of the VC machine. This setup reduces latency from Charon to the consensus layer, as well as keeping the public-internet connected clients separate from the clients that hold the validator private keys. If Charon and the VC connect over an untrusted network, the connection should be encrypted (VPN, Kubernetes [CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) etc). + +## Node Configuration + +Cluster sizes that allow for Byzantine Fault Tolerance are recommended as they are safer than clusters with simply Crash Fault Tolerance (See this guide for reference - [Cluster Size and Resilience](../../learn/charon/cluster-configuration.md#cluster-size-and-resilience)). A minimum of four Charon nodes is strongly recommended for this reason. + +## MEV-Boost Relays + +MEV relays are configured at the Consensus Layer or MEV-boost client level. Refer to our [guide](../../advanced-and-troubleshooting/advanced/enable-mev.mdx) to ensure all necessary configuration has been applied to your clients. As with all validators, low latency during proposal opportunities is extremely important. By default, MEV-Boost waits for all configured relays to return a bid, or will timeout if any have not returned a bid within 950ms. This default timeout is generally too slow for a distributed cluster (think of this time as additive to the time it takes the cluster to come to consensus, both of which need to happen within a 2 second window for optimal proposal broadcasting). It is likely better to only list relays that are located geographically near your node, so that once all relays respond (e.g. in < 50ms) your cluster will move forward with the proposal. + +Use Charon's [`test mev` command](test-a-cluster.mdx#test-mev-relay) to test a number of your preferred relays, and select the two or three relays with the lowest latency to your node(s), you do not need to have the same relays on each node in a cluster. + +## Client Diversity + +Obol clusters should consist of a mix of different consensus, execution, and validator clients. Charon can't [detect client failures](../../learn/further-reading/ethereum_and_dvt.md#deep-dive-into-dvt-and-charons-architecture) if all nodes are using the same client. At a minimum, no single client should comprise the [threshold](../../learn/charon/cluster-configuration.md#cluster-size-and-resilience) of nodes in the cluster. For example: + +A 7 node cluster with 4 Teku, 2 Lodestar and 1 Nimbus for validator clients **does not** have client error safety since the threshold (4) of votes can be met with just the Teku client. + +A 7 node cluster with 3 Teku, 3 Lodestar and 1 Nimbus for validator clients **is safe against a single client bug** as the threshold is not met by any one client. + +Keep in mind that client diversity includes EL, CL and VC clients and each layer needs an appropriate mix for optimal security. + +Remote signers can be included as well, such as Web3signer or Dirk. A diversity of private key infrastructure setups further reduces the risk of total key compromise. + +Tested client combinations can be found in the [release notes](https://github.com/ObolNetwork/charon/releases) for each Charon version. + +## Execution Layer Configuration + +When available on the EL client (e.g Nethermind), blob inclusion for locally-built blocks should be set to 0. Setting blob count to 0 for locally-built blocks avoids the additional latency of gathering blob transactions, which matters when falling back from MEV relay blocks under time pressure. + +## Metrics Monitoring + +Node operators should push [standard monitoring](../start/obol-monitoring.mdx) (Prometheus) and logging (Loki) data to Obol Labs' core team's cloud infrastructure for in-depth analysis of performance data and to assist during potential issues that may arise. The logging and metrics configuration values will be provided by the Obol team during onboarding. + +It is recommended that operators independently store information on their node health over the course of the validator lifecycle as well as any information on validator performance that they collect during the normal life cycle of a validator. + +## Obol Splits + +Leveraging [Obol Splits](../../learn/intro/obol-splits.md) smart contracts allows for non-custodial fund handling and allows for net customer payouts in an ongoing manner. Obol Splits ensure no commingling of funds across customers, and maintain full non-custodial integrity. Read more about Obol Splits [here](../../learn/intro/frequently-asked-questions.mdx#obol-splits). + +## Deposit Process + +Deposit processes can be done via an automated script. This can be used for DV clusters until they reach the desired number of validators. + +It is important to allow time for the validators to be activated (see current [queue](https://beaconcha.in/validators/queues)). + +Consider using batching smart contracts to reduce the gas cost of a script, but take caution in their integration not to make an invalid deposit. diff --git a/versioned_docs/version-v1.9/run-a-dv/prepare/how_where_dvs.md b/versioned_docs/version-v1.9/run-a-dv/prepare/how_where_dvs.md new file mode 100644 index 0000000000..1c94049a40 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/prepare/how_where_dvs.md @@ -0,0 +1,43 @@ +--- +description: "How and where to run DVs" +sidebar_label: "How and Where To Run DVs" +slug: /run-a-dv/prepare/how_where_dvs +--- + +# How and Where To Run DVs + +## Launchers and Deployment Tooling + +* [Obol CDVN](https://github.com/ObolNetwork/charon-distributed-validator-node) +* [Obol K8s](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) +* [Obol Helm Charts](https://github.com/ObolNetwork/helm-charts) +* [Obol Ansible Playbooks](https://github.com/ObolNetwork/obol-ansible) +* [Dappnode](https://docs.dappnode.io/docs/user/staking/ethereum/dvt-technologies/obol-network/) +* [Stereum](https://stereum.net/) +* [Sedge](https://github.com/ObolNetwork/sedge/blob/develop/docs/docs/quickstart/charon.mdx) +* [Terraform Charon Relay](https://github.com/ObolNetwork/terraform-charon-relay) +* [Terraform Grafana Charon dashboards](https://github.com/ObolNetwork/terraform-grafana-dashboards) + +## Quickstart Guides + +* [Run a DV alone](../start/create-a-dv-alone.mdx) +* [Run a DV as a group](../start/create-a-dv-with-a-group.mdx) + +## CL+VC Combinations: + +**Legend** + +* ✅: All duties succeed in testing +* 🟡: All duties succeed in testing, except non-penalised aggregation duties +* 🟠: Duties may fail for this combination +* 🔴: One or more duties fails consistently + +| Validator 👉 Consensus 👇 | Teku v24.10.3 | Lighthouse v5.3.0 | Lodestar v1.23.0 | Nimbus v24.10.0 | Prysm v5.1.2 | Remarks | +| ------------------------- | ------------- | ----------------- | ---------------- | --------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Teku v24.10.3 | ✅ | 🟡 | ✅ | ✅ | 🟠 | Teku `beacon node` needs the `--validators-graffiti-client-append-format=DISABLED` flag in order to produce blocks properly. Teku `validator client` is only failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. | +| Lighthouse v5.3.0 | ✅ | 🟡 | ✅ | ✅ | ✅ | Lighthouse `validator client` is only failing aggregation duties, which are not directly penalised but impact network density at high scale. | +| Lodestar v1.23.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Nimbus v24.10.0 | ✅ | 🟡 | ✅ | ✅ | 🟠 | | +| Prysm v5.1.2 | ✅ | 🟡 | ✅ | ✅ | ✅ | Prysm `validator client` is failing aggregation duties 50% of the time, which are not directly penalised but impact network density at high scale. In some combinations rare failures of attestation and proposal duties were observed (0-2% per epoch). | + +Note: for the most recent compatibility information, please see the [release notes](https://github.com/ObolNetwork/charon/releases/) from the most recent release of Charon. diff --git a/versioned_docs/version-v1.9/run-a-dv/prepare/test-a-cluster.mdx b/versioned_docs/version-v1.9/run-a-dv/prepare/test-a-cluster.mdx new file mode 100644 index 0000000000..2517f2bea9 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/prepare/test-a-cluster.mdx @@ -0,0 +1,641 @@ +--- +sidebar_label: "Test a Cluster" +slug: /run-a-dv/prepare/test-a-cluster +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Test a Cluster + +Charon test commands are designed to help you evaluate the performance and readiness of your candidate cluster. It allows you to test your connection to other Charon peers, the performance of your beacon node(s), the readiness of your validator client, the performance of the MEV relays you will be using and the infrastructure on which you will run the cluster. It prints a performance report to the standard output (which can be omitted with the `--quiet` flag) and a machine-readable JSON format of the report if the `--output-json` flag is set. + +:::tip +Adding the `--publish` flag to the below commands, and running the command from the directory containing your `.charon` folder, will submit the test results to the [Obol API](../../api/what-is-this-api.md). Publishing your performance reports grows the staking node dataset, and allows Obol and Ethereum development teams to make data-driven choices regarding the required specs for validating Ethereum. We hope you will consider opting in. +::: + + + +**Test all** + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-definition-file="./.charon/cluster-definition.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test + +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test all \ + --peers-lock-file="./.charon/cluster-lock.json" \ + --beacon-endpoints="http://127.0.0.1:5052/" \ + --beacon-load-test \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test +``` + + + + + + + +:::info +If you are running Charon using the [charon-distributed-validator-node repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), services like the beacon node and validator client are hosted locally. To run the `beacon` node and `validator` client tests, you need to point them toward the correct Docker container, this includes specifying the Docker container’s network. Check your docker networks with the command `docker network ls`. When you run the test command, specify the Docker network with `--network `. + +Read more about docker networking [here](https://docs.docker.com/engine/network/). +::: + +**Test all** + +Intended for running tests across all categories. Each flag should have a prefix for its category (i.e.: the flag `--endpoints` from the beacon tests becomes `--beacon-endpoints`). For details about each category refer to their respective sections. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" \ + --mev-endpoints="\ +https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi-helix.aestus.live,\ +https://0x821f2a65afb70e7f2e820a925a9b4c80a159620582c1766b1b09729fec178b11ea22abb3a51f07b288be815a1a2ff516@bloxroute.hoodi.blxrbdn.com,\ +https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net,\ +https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money,\ +https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. MEV relays are required to create real blocks. Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--peers-enrs` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test all \ + --peers-enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" + +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--peers-definition-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test all \ + --peers-definition-file="/opt/charon/test/.charon/cluster-definition.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--peers-lock-file` flag. +* Running beacon node(s) towards which tests will be executed, supplied to `--beacon-endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. +* Running validator client towards which tests will be executed. +* Running MEV relay(s) towards which tests will be executed, supplied to `--mev-endpoints` flag. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--mev-beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run --network="charon-distributed-validator-node_dvnode" -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test all \ + --peers-lock-file="/opt/charon/test/.charon/cluster-lock.json" \ + --peers-private-key-file="/opt/charon/test/.charon/charon-enr-private-key" \ + --beacon-endpoints="http://lighthouse:5052/" \ + --beacon-simulation-file-dir="/opt/charon/test" \ + --beacon-load-test \ + --validator-api-address="lodestar:5064" \ + --mev-endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --mev-beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" \ + --mev-load-test \ + --infra-disk-io-test-file-dir="/opt/charon/test" +``` + + + + + + + +### Test connection to peers + +Run tests towards other Charon peers to evaluate the effectiveness of a potential cluster setup. The command sets up a libp2p node, similarly to what Charon normally does. This test command **has to be run simultaneously with the other peers**. After the node is up it waits for other peers to get their nodes up and running, retrying the connection every 3 seconds. The libp2p node connects to relays (configurable with `p2p-relays` flag) and to other libp2p nodes via TCP. Other peer nodes are discoverable by using their ENRs. Note that for a peer to be successfully discovered, it needs to be connected to the same relay. After completion of the test suite the libp2p node stays alive (duration configurable with `keep-alive` flag) for other peers to continue testing against it. The node can be forcefully stopped as well. + +To be able to establish direct connection, you have to ensure: + +* Your machine is publicly accessible on the internet or at least a specific port is. +* You add flag `p2p-tcp-address` (i.e.: `127.0.0.1:9001`) flag and the port specified in it is free and publicly accessible. +* You add the flag `p2p-external-ip` (i.e.: `8.8.8.8`) and specify your public IP. + +If all points are satisfied by you and the other peers, you should be able to establish a direct TCP connection between each other. Note that a relay is still required, as it is used for peer discovery. + +Based on which stage you are with your cluster creation, some steps are eased. + + + +**Pre-requisites** + +* [ENR private key](../../learn/charon/charon-cli-reference.md#creating-an-enr-for-charon). +* Peers' ENRs, supplied to the `--enrs` flag. + +**Example run** + +```sh +charon alpha test peers \ + --enrs="enr:-HW4QMno_MB_ID6GFVxoIQAHHVHZZZjzFctxtX2tm9D95tvaPbHathi8YUP8jh8v2YUAVu2fYWEOB_BT14pt8QgiGg2AgmlkgnY0iXNlY3AyNTZrMaECdpnK83s0dbBwCaEfDIkQ-3nJkkC93STvv6Vmi0bYlzg,enr:-HW4QO2vefLueTBEUGly5hkcpL7NWdMKWx7Nuy9f7z6XZInCbFAc0IZj6bsnmj-Wi4ElS6jNa0Mge5Rkc2WGTVemas2AgmlkgnY0iXNlY3AyNTZrMaECR9SmYQ_1HRgJmNxvh_ER2Sxx78HgKKgKaOkCROYwaDY" +``` + + + +**Pre-requisites** + +* Cluster definition file, supplied to the `--definition-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --definition-file="./.charon/cluster-definition.json" +``` + + + +**Pre-requisites** + +* Cluster lock file, supplied to the `--lock-file` flag. + +**Example run** + +```sh +charon alpha test peers \ + --lock-file="./.charon/cluster-lock.json" +``` + + + +### Test beacon node + +Run tests on beacon node(s), to evaluate their effectiveness for a Distributed Validator cluster. The beacon node is usually the client doing the most work in a validating stack, especially with a high number of validators being serviced by the validator client(s) and Charon(s) that depend on it. + + + +Regular tests intended for relatively fast run, without putting any major load on any tested system. + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="https://ethereum-hoodi-beacon-api.publicnode.com,https://ethereum-sepolia-beacon-api.publicnode.com" +``` + + + +Load tests intended for more time consuming run. Beacon nodes are put under heavy load. + +These tests include simulated workloads for an increasing number of validators, and the process takes some time (approximately \~33 minutes). It is normal to observe some warnings during the simulations. + +A file with detailed results about simulations done is saved at the current working directory (configurable by `--simulation-file-dir` flag). + +**Pre-requisites** + +* Running beacon node(s) towards which tests will be executed, supplied to `--endpoints` flag. It is important that the node is expecting to handle huge load and that it is **not** a publicly accessible one, which can block you. + +**Example run** + +```sh +charon alpha test beacon \ + --endpoints="http://127.0.0.1:5052/" \ + --load-test +``` + + + +### Test validator client + +Run tests towards your validator client, to evaluate its effectiveness for a Distributed Validator cluster. + +Default endpoint for validator and port is used at `127.0.0.1:3600`. This can be changed by supplying different endpoint to the `--validator-api-address` flag. + +#### Pre-requisites + +* Running validator client towards which tests will be executed. + +#### Example run + +```sh +charon alpha test validator +``` + +### Test MEV relay + +Run tests towards MEV relays, to evaluate their effectiveness for a Distributed Validator cluster. If MEV-Boost clients are configured for the distributed validator nodes, it is of utmost importance that the relays they connect to are fast and reliable. If not, the chance of missing a block proposal increases significantly. Supplying `--beacon-node-endpoint` and `--load-test` flags allows the test to ask relays for real MEV headers, increasing the accuracy (and duration) of this test. + +At least 1 endpoint is required to be supplied to the `--endpoints` flag. + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +charon alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.9.0 alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" +``` + + + +**Pre-requisites** + +* Running MEV relay(s) towards which tests will be executed. +* Running beacon node which will be used for fetching data required by the MEV relay for block creation, supplied to `--beacon-node-endpoint`. There is no restrictions on the node and a public one can be used. + +**Example run** + +```sh +docker run obolnetwork/charon:v1.9.0 alpha test mev \ + --endpoints="\ +https://0xa15b52576bcbf1072f4a011c0f99f9fb6c66f3e1ff321f11f461d15e31b1cb359caa092c71bbded0bae5b5ea401aab7e@aestus.live,\ +https://0xa7ab7a996c8584251c8f925da3170bdfd6ebc75d50f5ddc4050a6fdc77f2a3b5fce2cc750d0865e05d7228af97d69561@agnostic-relay.net,\ +https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,\ +https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,\ +https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@regional.titanrelay.xyz,\ +https://0x8c4ed5e24fe5c6ae21018437bde147693f68cda427cd1122cf20819c30eda7ed74f72dece09bb313f2a1855595ab677d@global.titanrelay.xyz" \ + --load-test \ + --beacon-node-endpoint="https://ethereum-beacon-api.publicnode.com" +``` + + + + + +### Test machine and network performance + +Run tests of your machine and network, to evaluate their effectiveness for a Distributed Validator cluster. Distributed Validators need stable, low-latency, internet, a reasonable amount of RAM, and a highly performant disk drive for storage. This test aims to analyse these requirements to give an overview of the systems suitability. + + + +**Pre-requisites** + +The executable storage tests require `fio` to be installed on your host machine. Read more about `fio` [here](https://fio.readthedocs.io/en/latest/fio_doc.html). + +**Example run** + +```sh +charon alpha test infra +``` + + + +**Example run** + +```sh +docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/opt/charon/test" obolnetwork/charon:v1.9.0 alpha test infra \ + --disk-io-test-file-dir=/opt/charon/test +``` + + diff --git a/versioned_docs/version-v1.9/run-a-dv/running/README.md b/versioned_docs/version-v1.9/run-a-dv/running/README.md new file mode 100644 index 0000000000..8d5facc05a --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Running a DV" +slug: /run-a-dv/running +--- + +# Running a DV + diff --git a/versioned_docs/version-v1.9/run-a-dv/running/activate-a-dv.md b/versioned_docs/version-v1.9/run-a-dv/running/activate-a-dv.md new file mode 100644 index 0000000000..a879a2c3d8 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/activate-a-dv.md @@ -0,0 +1,112 @@ +--- +description: "Learn how to activate your distributed validator cluster using the new deposit flow with support for compounding validators and OVM integration." +sidebar_label: "Activate a DV" +slug: /run-a-dv/running/activate-a-dv +--- + +# Activate a DV + +If you have successfully created a distributed validator and you are ready to activate it, congratulations! 🎉 + +Once you have connected all of your Charon clients together, synced all of your Ethereum nodes such that the monitoring indicates that they are all healthy and ready to operate, **ONE operator** may proceed to deposit and activate the validator(s). + +The `deposit-data.json` to be used to deposit will be located in each operator's `.charon` folder. The copies across every node should be identical and any of them can be uploaded. + +:::danger +If you are being given a `deposit-data.json` file that you didn't generate yourself, please take extreme care to ensure this operator has not given you a malicious `deposit-data.json` file that is not the one you expect. Cross reference the files from multiple operators if there is any doubt. Activating the wrong validator or an invalid deposit could result in complete theft or loss of funds. +::: + +The Ethereum Pectra upgrade enables validators with `0x02` Compounding Withdrawal Credentials to hold balances exceeding 32 ETH and automatically reap the benefits of compounding rewards. The Launchpad provides an intuitive interface to manage these extended balances. + +*** + +## 1. New Deposit Experience Overview + +This new flow supports deposits to validators with any standard withdrawal address, including **EOA (Externally Owned Account)** addresses, and streamlines the activation and top-up process. + +### A. Critical Distinction (OVM Users MUST Use This Flow) + +| Withdrawal Address Type | Recommended Flow | Reason | +| ---------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **OVM (Obol Vault Manager)** | **MANDATORY:** Deposit via the Cluster Details Page flow. | This ensures the OVM smart contract correctly tracks the deposited amount as principal stake and manages subsequent reward accounting. Bypassing the OVM requires manual accounting adjustments. | +| **EOA (Standard Wallet)** | RECOMMENDED: Deposit via the Cluster Details Page flow. | Allows direct deposit without needing to manually upload a deposit data file. Also supports top-ups. | + +:::danger +🚨 In OVMs, only addresses with `DEPOSIT_ROLE` can perform deposits for activation and top-ups. Read more about how to assign roles [here](../../advanced-and-troubleshooting/advanced/assign-ovm-roles.md). +::: + +![](/img/gitbook/OVMDeposit1.png) + +### B. Initial Deposit Options + +There are three strategic ways to break down a large deposit (e.g., 1000 ETH) for activation, all of which use compounding validators: + +| Option | Strategy | Pros | Cons | +| ------ | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| **1** | **32 ETH + Top-Up** (e.g., 32 ETH + 968 ETH) | Allows any amount, even decimals. Simple, two distinct transactions. | The 968 ETH top-up transaction **must wait** for the initial 32 ETH validator to become Active (opportunity cost). | +| **2** | **Single Activation (>32 ETH)** (e.g., 1000 ETH) | Multiple deposits are bundled into a single multi-call transaction. This eliminates opportunity cost and ensures all ETH yields rewards immediately. | Decimal amounts of ETH are not supported. Transaction gas cost could be high depending upon the amount chosen. | +| **3** | **Activate Multiple Validators** (distributing 1000 ETH) | Similar to Option 2, but leaves more room for individual top-ups later. | Creates more load on nodes due to the higher validator count. | + +![Deposit](/img/gitbook/Screenshot-2026-02-11-at-16.36.53.png) + +## 2. Allocation & Submission + +After choosing a deposit option, the user specifies the total amount. Pressing continue provides two allocation options: + +* **Recommended Allocation:** A suggestion for where the deposit amount should be staked based on an optimization strategy (see Section 3). +* **Manual Allocation:** If the recommendation doesn't fit your preference, you can allocate deposits manually. + +Once the allocation is solidified, users review and send transactions. The amount is sent to the deposit queue for activation or top-up based on the chosen strategy. + +![](/img/gitbook/OVMDeposit3.png) + +![](/img/gitbook/OVMDeposit4.png) + +## 3. Technical Details + +### A. How Large Activations (>32 ETH) are Made (Option 2) + +When a compounding (`0x02`) validator is created with an amount greater than 32 ETH (e.g., 40 ETH), Charon generates the following deposit files (1 ETH, 8 ETH, 32 ETH, 256 ETH). When performing the initial deposit through OVM, the launchpad **bundles multiple deposits into a single multi-call transaction.** When deposits are made via EOA, the batching is done using deposit contracts built by [Pier Two](https://docs.piertwo.com/docs/batch-deposit-contract). Batching results in a slightly higher gas cost than a single 32 ETH deposit. While doing top-ups, any deposit amount can be used. + +### B. Recommended Allocation Strategy + +The recommended allocation follows this rule - always deposit in validator with highest effective balance less than 1920 ETH. This is to keep the validator count low and benefit from compounding rewards. For example, to deposit 1000 ETH: + +* If there is no active validator, we recommend activating with 1000 ETH in a single validator. Or 32 ETH first and 968 ETH later in the same validator. +* If there is an active validator with balance of 920 ETH or less, we recommend depositing in the same validator to reach suggested cap of 1920 ETH or less. +* If there is an active validator with balance of more than 920 ETH, let's say 1200 ETH, we recommend filling this validator to 1920 ETH by adding 720 ETH and using remaining 280 ETH to activate a new validator. + +### C. Troubleshooting Top-Ups + +If a top-up fails, check the following reasons: + +* **Validator Type:** The validator is **not a `0x02` type** and therefore does not support top-ups. +* **Maximum Balance:** The validator has already **reached the maximum suggested balance cap of 1920 ETH**. +* **Status:** There is **no active validator** to receive the top-up amount. + +### D. How to Adjust Principal Inside the OVM + +When a user bypasses deposits via OVM and deposits directly, the amount of principal stake will not be accrued inside the OVM. This can create problems in the distribute flow which needs principal and rewards to be correctly accounted. OVM allows the Owner to set the correct principal using `setAmountOfPrincipalStake`. Finding the correct amount to set is a manual process. For example, a user deposited 1782 ETH into 3 validators and forgot the amount deposited. If the validators are active or deposits are successful, the user can check on the beacon chain to find deposits into each validator. The total should sum up to 1782 ETH. + +![](/img/gitbook/OVMDeposit5.png) + +## 4. Legacy Deposit Flow (To be Deprecated) + +The Legacy Flow is the pre-Pectra experience and should be avoided, especially by OVM users. + +* This flow is best suited for activating older `0x01` (BLS) validators. +* It **does not support top-ups** with arbitrary amounts into compounding (`0x02`) validators. +* The user must select the number of validators first, and the total deposit amount is calculated after (Amount \* Number of Validators). +* It lacks the integrated Recommended Allocation strategy - it is manually governed by the user. +* If one of the withdrawal addresses is OVM, a warning is displayed with strong suggestions to use the new deposit flow in the cluster page to avoid accounting issues of principal and rewards inside the OVM. Legacy flow will bypass deposits via OVM and directly to validators. As a result, the user will have to manually adjust principal and rewards after. Read more about [how to adjust the principal inside the OVM](activate-a-dv.md#d-how-to-adjust-principal-inside-the-ovm). + +### Legacy Deposit Tools + +If you need to use the legacy flow (not recommended for OVM users), you can use: + +* [Obol Distributed Validator Launchpad](https://launchpad.obol.org/deposit/advisories/) +* [ethereum.org Staking Launchpad](https://launchpad.ethereum.org/) + +:::info +The activation process can take a minimum of 16 hours, with the maximum time to activation being dictated by the length of the activation queue, which can be weeks. +::: diff --git a/versioned_docs/version-v1.9/run-a-dv/running/claim-rewards.md b/versioned_docs/version-v1.9/run-a-dv/running/claim-rewards.md new file mode 100644 index 0000000000..5fbdf9bd4d --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/claim-rewards.md @@ -0,0 +1,101 @@ +--- +description: "Learn how to claim rewards from your distributed validator cluster, including the new 3-step process for 0x02 validators and legacy OWR flow." +sidebar_label: "Claim Rewards" +slug: /run-a-dv/running/claim-rewards +--- + +# Claim Rewards + +For every epoch, active validators earn ETH rewards from both the consensus layer and the execution layer. The consensus layer rewards are derived from validator duties such as attestation, proposals, and sync committees. These rewards are accumulated in the validator's withdrawal address. Execution rewards, which are earned from MEV and transaction priority tips, are accumulated in the fee recipient address. + +*** + +## New Claim Rewards Process (0x02 Validators) + +Whether your cluster is created with OVMs as withdrawal address or EOA as withdrawal address, the process is similar. There are three steps: + +### 1. Withdraw Rewards / Principal + +WWith the introduction of compounding, `0x02` validators no longer support automatic withdrawal sweeps to compound rewards. As a result, rewards are not sent directly to the withdrawal address. Instead, the withdrawal address must send a withdrawal request. + +1. Refer to the following documentation to withdraw rewards: + * If the withdrawal address is an **EOA**: See the [Request Withdrawal guide](request-withdrawal.md) for EOA-specific instructions. + * If the withdrawal address is an **OVM**: See the [Request Withdrawal guide](request-withdrawal.md) for OVM-specific instructions. + +:::warning +Be very careful about the amount of ETH you withdraw, as it will govern whether the amount will be treated as principal or rewards. Read more about this in the [withdrawal request FAQ](request-withdrawal.md#3-how-to-decide-initial-withdrawal-amount). +::: + +2. If there are already undistributed rewards, make sure to distribute them before the withdrawal is processed (unless you want to send them to the principal recipient). BThis is because, after the withdrawal is processed, the new withdrawal amount and any previously undistributed rewards may combine and cross the principal threshold. + +:::info +💡 In case of `0x01` validators, no withdrawal is required. Withdrawal skimming happens on a regular basis and will be sent to OVM balance. If you are using legacy Obol splits contracts with `0x01` validators, also called OWRs, then you can jump to the distribute stage (see [Legacy OWR Flow](claim-rewards.md#legacy-owr-flow-deprecated) below). +::: + +### 2. Distribute the Rewards + +If you are using OVM, distribute the ETH that has been withdrawn from the validators. Upon distribution, it will be sent to either the principal recipient or will be sent as rewards and ready to be claimed on the operator page. + +:::info +💡 The amount of ETH withdrawn in the previous step will be sent to OVM. If the OVM balance is greater than the principal threshold, upon distribution the ETH from OVM balance will be sent to the principal address. If the OVM balance is below the principal threshold, it will be sent to the fee recipient splitter. If rewards are sent to the fee recipient splitter, they will be distributed again according to split configuration. But all of these multiple distributions are batched together under a single distribute action. +::: + +:::info +💡 For legacy `0x01` validators with OWR withdrawal addresses, distribute works just like before. Click the distribute icon to trigger the distribution. +::: + +### 3. Claim + +Once the funds are distributed, go to the [Operator Dashboard](https://launchpad.obol.org/) to claim the rewards. + +*** + +## Legacy OWR Flow (Deprecated) + +:::warning +This section documents the legacy OWR (Optimistic Withdrawal Recipient) flow for older `0x01` validators. For new clusters with `0x02` validators, please use the [New Claim Rewards Process](claim-rewards.md#new-claim-rewards-process-0x02-validators) above. +::: + +The method for claiming rewards depends on the cluster's withdrawal configuration, whether it's an [**OWR**](../../learn/intro/obol-splits.md#optimistic-withdrawal-recipient) or an [**Exitable Withdrawal Configuration**](../../learn/intro/obol-splits.md#obol-validator-managers). The table below outlines the latest details on how and where to claim rewards. + +### Claim Status {#claim-status} +| Withdrawal Configuration | Subcategory Description | Is supported on Launchpad? | Where to claim? | +| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Claim principal + rewards without splits - Exit and get rewards | To claim principal or rewards without splits, users currently have to exit the validator. | ✅ | Cluster details page in the Operator Dashboard. For example, [here](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 2. Splits only rewards using OWR - ETH | For all clusters with ETH rewards. Requires two steps: (1) Distribute on cluster details page, (2) Claim on operator page. | ✅ | Step 1: Cluster details page - Click **Distribute** button for each OWR. Step 2: Operator page - Claim your share. For example, [here](https://hoodi.launchpad.obol.org/cluster/details/?lockHash=0x42833298f3c767b866615814dd9f86ce35ed2f89bf3d397d5f353a0ad5a38013). | +| 3. Split principal + rewards - ETH | For clusters configured to split both principal and rewards. | ✅ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 4. Splits non-ETH rewards using any withdrawal config - wstETH or weETH | For Lido and EtherFi clusters earning rewards in protocol-specific tokens. | In Progress ➡️ | Operators currently need to use the UI provided by Splits.org. For example, a [Lido Split](https://app.splits.org/accounts/0x845aF36663a9908D9E46101e3CC658FbCEB783a8/?chainId=1). | +| 5. Lido CSM rewards - wstETH | For all Lido CSM clusters earning wstETH rewards. | In Progress ➡️ | Similar to row number 3, use the Splits UI. More details can be found at the bottom of [this page](../integrations/lido-csm.md). | + +### Claim Flow {#claim-flow} +To understand how claims via Launchpad work, it is highly recommended to first understand how splits work. More details are available [**here**](../../learn/intro/obol-splits.md). The flowchart below summarizes how an operator and a non-operator can interact with split contracts to facilitate claims: + +![](/img/gitbook/image-56.png) + +**Updated OWR Process:** + +1. All validator rewards are accumulated in the validator's withdrawal address, which is an OWR (Optimistic Withdrawal Recipient) contract. +2. **Distribute on Cluster Details Page**: On the cluster details page, you will see a **Distribute** button for each OWR. Click the Distribute button to send rewards from the OWR to the Split Main contract. This step must be completed before claiming. +3. **Claim on Operator Page**: After distribution is complete, navigate to the operator page to claim your share of the rewards. The rewards will be distributed according to the split configuration set at cluster creation. +4. The Split Main contract sends proportional rewards to each operator based on their configured split percentage. + +:::info +Note: There is no longer a "Claim All" button on the cluster details page. The process now requires two steps: first distribute in the cluster details page, then claim at the operator page. +::: + +### Launchpad Edge Cases {#launchpad-edge-cases} +We are constantly improving the user experience. Below are some edge cases to avoid confusion: + +#### Case 1: You need to distribute before claiming + +Make sure you have clicked the **Distribute** button for each OWR in the cluster details page before attempting to claim rewards at the operator page. If you try to claim before distributing, there may be no rewards available to claim. + +#### Case 2: Multiple OWRs in a cluster + +If your cluster has multiple OWRs (one per validator), you will see a separate **Distribute** button for each OWR. You need to distribute from each OWR individually before claiming your rewards. After all distributions are complete, you can claim your total share from the operator page. + +#### Case 3: You just created a new cluster with no active validators or rewards, but it shows claimable amounts + +![](/img/gitbook/image-89.png) + +The amount shown here is from a previous case and is now sitting in the Split Main, ready to be claimed. Unfortunately, it is not possible to associate the Split Main balance of an address with a specific cluster. If you are part of multiple clusters, your Split Main balance will appear next to all claim buttons, regardless of the cluster. We are working on a fix to avoid this confusion. diff --git a/versioned_docs/version-v1.9/run-a-dv/running/distribute-rewards.md b/versioned_docs/version-v1.9/run-a-dv/running/distribute-rewards.md new file mode 100644 index 0000000000..4d4d32c7a5 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/distribute-rewards.md @@ -0,0 +1,49 @@ +--- +description: "Learn how distribution works for OVM and splitter contracts, including how principal and rewards are distributed based on principal threshold." +sidebar_label: "Distribute Rewards" +slug: /run-a-dv/running/distribute-rewards +--- + +# Distribute Rewards + +The distribution action allows the user to distribute funds from their OVM and splitters to the claim address. As a result, the distribution action is only available when either the withdrawal address is an OVM or the fee recipient of the withdrawal configuration is a splitter address. Once amounts are distributed, they can be claimed on the operator page or home page of the launchpad. + +## Overview + +1. The distribution action allows users to transfer the distributable amount as principal or rewards. It comprises of two actions in a single click: + 1. Transfer the amount from OVM balance to Principal recipient or Rewards Recipient, depending on whether the OVM's Balance has crossed the Principal Threshold. + 2. If the Rewards Recipient is a splitter contract, split the amount according to respective share of addresses in the splitter config and transfer it to the warehouse contract where the amount is ready to be claimed. The amount from all the various splitter warehouses can be claimed from the main Operator Dashboard. +2. The distribution applies to the full available amount. On clicking distribute, the user will see the following modal: + 1. The fields are explained below: + 1. **You are distributing:** This is the sum of your OVM Balance + Splitter's Balance that will be distributed. First the OVM is distributed and then the splitter. + 2. **Total Validator Balance:** Total Validator Balance of all the validators associated to this OVM - principal + rewards + 3. **Principal Threshold:** Amount of ETH required in your OVM balance to be classified as Principal in order for it to be sent to the Principal Recipient. To cross the threshold, withdraw more ETH using the withdrawal flow or exit the validators. + +![](/img/gitbook/OVMDistribute1.png) + +2. The table shows where the principal or rewards flow to after distribution. When the reward recipient is a splitter, rewards are not sent directly to the addresses in the splitter configuration. Instead, they become available to claim from the operator distributions page. If a user is part of multiple splitter configurations, it is recommended to distribute across all of them and claim all at once to optimize for gas fees paid. To learn more about the logic of distribution, read the [Understanding Distribution in Detail](distribute-rewards.md#understanding-distribution-in-detail) section. +3. After the distribute transaction is successfully sent, the success page shows a summary of the amount distributed and the new principal + rewards. If rewards were distributed, they will be ready to claim on the dashboard page. + +![](/img/gitbook/OVMDistribute2.png) + +## Understanding Distribution in Detail + +1. The distribution starts by looking at the total distributable amount (`DA`) that is comprised of OVM's balance (`OB`) and Splitter's balance (`SB`). +2. Upon sending the distribute transaction: + 1. `OB` balance is checked against principal threshold (`PT`) and current principal (`CP`), both of which are tracked in the OVM contract. + 1. **If `OB` > `PT` and `CP` > `OB`:** All of `OB` is transferred to principal recipient and tracked principal is debited by `OB`, in other words, the new principal in OVM is `CP` - `OB` + 2. **If `OB` > `PT` and `CP` < `OB`:** Since there is not sufficient principal for distributing all of `OB`, only `CP` will be distributed as principal and will be sent to the principal recipient. The remainder of `OB` - `CP` will be sent to the reward recipient as rewards. The reward recipient could be a splitter contract, therefore a new splitter contract balance can be `SBnew` = `SB` + `OB` - `CP`. Current Principal will be set to 0 as no principal is remaining. + 3. **If `OB` < `PT`:** All of `OB` will be sent to reward recipient as rewards. This reward recipient could be a splitter contract so the new splitter contract balance can be `SBnew` = `SB` + `OB` + 2. If the reward recipient is a splitter, `SBnew` balance (Previous splitter balance + new ETH from the OVM if it was rewards) will be distributed and all of the addresses in splitter config can now claim their reward on the dashboard. + +### Distribution Flow Summary + +| Condition | OVM Balance (`OB`) vs Principal Threshold (`PT`) | Current Principal (`CP`) vs `OB` | Distribution Result | +| ---------- | ------------------------------------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| **Case 1** | `OB` > `PT` | `CP` > `OB` |

All OB → Principal Recipient
New Principal = CP - OB

| +| **Case 2** | `OB` > `PT` | `CP` < `OB` |

CP → Principal Recipient
OB - CP → Reward Recipient
New Principal = 0

| +| **Case 3** | `OB` < `PT` | N/A | All `OB` → Reward Recipient | + +:::info +💡 Remember: If the reward recipient is a splitter contract, the distributed rewards will be available to claim on the Operator Dashboard, not sent directly to individual addresses in the splitter configuration. +::: diff --git a/versioned_docs/version-v1.9/run-a-dv/running/exit-a-dv.mdx b/versioned_docs/version-v1.9/run-a-dv/running/exit-a-dv.mdx new file mode 100644 index 0000000000..2cd1616702 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/exit-a-dv.mdx @@ -0,0 +1,988 @@ +--- +sidebar_label: "Exit a DV" +slug: /run-a-dv/running/exit-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Exit a DV + +### Introduction {#introduction} +Users looking to exit staking entirely and withdraw their full balance back have two options: + +1. **Exit via Withdrawal Address (Recommended for Post-Pectra):** If your cluster's withdrawal address is an EOA or OVM, you can trigger an EL exit directly from the Launchpad without needing validator keys or operator coordination. This is the simplest method and is described in the [Exit via Withdrawal Address](exit-a-dv.mdx#exit-via-withdrawal-address-post-pectra) section below. +2. **Exit via Validator Keys (Traditional Method):** This method requires signing and broadcasting a "voluntary exit" message with validator keys. In the case of a DV, Charon nodes need to broadcast a partial exit to the other nodes of the cluster. Once a threshold of partial exits has been received by any node, the full voluntary exit will be sent to the beacon chain. This process will take 27 hours or longer depending on the current length of the exit queue. Once the validator is exited, the principal plus unclaimed rewards will go to the withdrawal address of the validator. Depending on the cluster's withdrawal configuration, users can claim their proportion of principal and rewards. + +For the traditional validator key-based method, there are two ways to sign the partial exit and broadcast the full exit. Neither solution requires gas: + +1. **Using Charon's exit solution** - It is an Obol hosted solution which is facilitated by Obol APIs. It provides several benefits such as signing partial exits for multiple validators at once, live monitoring of partial exits status via Launchpad and ability to download partial exits and broadcast them later as required. Users don't have to worry about the intricacies of validator clients. Charon Exit abstracts all the complexity. +2. **Using the Validator Clients directly** - Users can also directly use the validator client that is connected to your Charon client to submit partial exits, as the client only signs a partial exit message using its share of the private key. Charon will combine the partial exit messages from the other operators. Once the threshold is reached, they are submitted to the beacon node. All of this is usually wrapped under a single command and hence users cannot download full exit signatures for broadcasting it later. In this case, users cannot use Launchpad to monitor exit status and will have to use Grafana to query the partial exit status. + +:::info +**For the traditional validator key-based exit method:** + +* A threshold of operators need to run the exit command for the exit to succeed. This is the same threshold as is specified during cluster creation. +* **Ensure that all operators within a cluster consistently use either the hosted solution (Charon Exit) or the non-hosted solution (Validator Client Exit). Mixing both solutions within the same cluster—where some operators use Charon Exit while others use Validator Client Exit—is not allowed.** +* In case of validator client native exits, partial exits can be broadcast by any validator client as long as the threshold for the cluster is reached. +* If a Charon client restarts after the exit command is run but before the threshold is reached, it will lose the partial exits it has received from the other nodes. If all Charon clients restart and thus all partial exits are lost before the required threshold of exit messages are received, operators will have to rebroadcast their partial exit messages. +* All operators need to use the same `EXIT_EPOCH` for the exit to be successful. Assuming you want to exit as soon as possible, the default epochs included in the below commands should be sufficient for the respective network. +::: + +*** + +## Exit via Withdrawal Address (Post-Pectra) + +Post-Pectra fork, withdrawal addresses of validators can trigger an EL (Execution Layer) exit directly. This method allows the withdrawal address (EOA or OVM) to initiate exits without requiring validator keys or coordination between operators. This is an alternative to the validator key-based exit methods described below. + +:::info +**When to use this method:** If your cluster's withdrawal address is an EOA or OVM, you can use this simpler method to exit validators directly from the Launchpad, without needing to coordinate with other operators or use validator keys. +::: + +### How to Trigger an EL Exit + +In the Launchpad, you can initiate an EL exit using the Exit validator button in the actions column of the validators table. To trigger an EL exit, you must meet one of the following conditions: + +* **Connected with the withdrawal address:** If the withdrawal address is an EOA (Externally Owned Account), you must be connected with that EOA wallet. +* **Have WITHDRAWAL\_ROLE:** If the withdrawal address of the validator is an OVM, you must have `WITHDRAWAL_ROLE` in that OVM. Read more about how to assign roles [here](../../advanced-and-troubleshooting/advanced/assign-ovm-roles.md). + +![](/img/gitbook/Screenshot-2026-02-11-at-16.46.19.png) + +### Step-by-Step Process + +1. **Initiate Exit:** Upon clicking the Exit validator button, you can multi-select the active validators you would like to exit. In the example below, there is only one active validator, so only one can be selected for the exit. + +![](/img/gitbook/Screenshot-2026-02-11-at-16.59.40.png) + +1. **Review and Confirm:** You will see a confirmation page showing the validators that will be exited. If you are sending exits via EOA, it will require exiting validators one by one. In the future, we will use EIP-7702 to perform a single-click exit for all validators. + +![](/img/gitbook/Screenshot-2026-02-11-at-17.01.17.png) + +1. **Transaction Submission:** Once the exit is submitted, a transaction will be sent with `0` as the withdrawal amount. This signals the beacon chain to exit the validator. Once the transaction is processed, validators will enter the `Active Exiting` stage. + +:::warning +**Important:** You must keep the nodes up as validators have only entered the exit queue. Once the exit is processed and there are no more active validators on the node, you can bring the node down. +::: + +4. **Exit Completion:** After the exit is complete, the total balance will be sent to the OVM after the required on-chain withdrawal sweep has finished. At this point, you can distribute the principal and rewards, which are then claimed via the operator page. + +![](/img/gitbook/ElExit4.png) + +![](/img/gitbook/ElExit5.png) + +![](/img/gitbook/ElExit6.png) + +:::danger +🚨 **Crucial Warning:** You **must** distribute any existing undistributed rewards _before_ the exit process finishes. If you do not perform this distribution beforehand, the exiting principal amount will be combined with the remaining rewards upon completion. This combined value will then incorrectly exceed the principal distribution threshold, which will cause the rewards to be mistakenly sent to the principal recipient when you initiate the final distribution. + +For more information on distribution, see the [Distribution guide](distribute-rewards.md). +::: + +*** + +## Exit via Validator Keys (Traditional Method) + +The following sections describe the traditional method of exiting validators using validator keys, which requires coordination between operators in the cluster. + +Choose the correct combination of: + +1. **Network** : Mainnet or Hoodi +2. **Exit Type** : Hosted (Charon) or Non-hosted (Validator client) +3. **Validator Quantity**: Exit single or Exit all validators: + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=256' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=256' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](/img/gitbook/image-1.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operators. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly)** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later)** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=hoodi \ +--epoch=256 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=hoodi \ +--epoch=256 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](/img/gitbook/image-1-1.png) + + ![](/img/gitbook/image-2.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](/img/gitbook/image-4.png) + + ![](/img/gitbook/image-5.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](/img/gitbook/image-6.png) + + ![](/img/gitbook/image-7.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-8.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=256 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=hoodi \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=hoodi \ +--exitEpoch=256 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will mismatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network hoodi \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indices can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network hoodi \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](/img/gitbook/image-9.png) + + ![](/img/gitbook/image-10.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](/img/gitbook/image-11.png) + + ![](/img/gitbook/image-12.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](/img/gitbook/image-13.png) + + ![](/img/gitbook/image-14.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](/img/gitbook/image-15.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Exit a distributed validator using DappNode** + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](/img/gitbook/image-17.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](/img/gitbook/image-18.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](/img/gitbook/image-19.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +Voluntary exit can be submitted directly through Charon. This approach is validator client agnostic as Charon abstracts validator client's native exit commands underneath. + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key="" \ +--exit-epoch=194048' +``` + +Replace `` with the validator's full pubkey (as visible in Ethereum). + + + +Following command signs partial exits for all validators. + +```sh +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit sign \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all \ +--exit-epoch=194048' +``` + + + +**Step 2: Monitor the Partial Exits' status** + +After a threshold of signed partial exits from node operators in the cluster is accumulated, a full (complete) exit can be created. For example, in the cluster below, only 2 out of 4 clusters have reached the threshold. Operators will have to wait for one more partial exit signature, either from operator 1 or 3 to create a full exit message. + +![](https://docs.obol.org/img/PartialExitsStatus.png) + +**Step 3: Broadcast the full exit** + +Once the partial exit threshold is reached, a full exit can be broadcasted from any of the operator. There are two options to do it, depending on your use-case + +1. **Fetch the full exit and broadcast instantaneously (Broadcast directly )** - users can choose it for a single validator or all validators in the cluster. +2. **Fetch the full exit and broadcast it later(Fetch & Broadcast later )** - users can choose it for a single validator or all validators in the cluster. + + + + + +Following command fetches full exit and broadcasts it instantaneously for a specific validator. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--validator-public-key=""' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Following command fetches full exits and broadcasts them instantaneously for all the validators that have reached a partial exit threshold. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--all' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Download Exits** : The following command downloads the full exit signature for a specific public key and stores it in a file. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--validator-public-key="" \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signature for a specific public key from the file and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-file="/opt/charon/.charon/"'' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Download Exits** : The following command downloads the full exit signature for all the active public keys and stores it in a directory. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit fetch \ +--all \ +--fetched-exit-path="/opt/charon/.charon"' +``` + +**Broadcast Exits** : The following command uses the full exit signatures from the directory and broadcasts it to the network. + +``` +docker exec -it charon-distributed-validator-node-charon-1 /bin/sh -c 'charon exit broadcast \ +--all \ +--beacon-node-endpoints="http://lighthouse:5052" \ +--exit-from-dir="/opt/charon/.charon"' +``` + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-public-keys= \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-teku-1 /opt/teku/bin/teku voluntary-exit \ +--beacon-node-api-endpoint="http://charon:3600/" \ +--validator-keys="/opt/charon/validator_keys:/opt/charon/validator_keys" \ +--network=mainnet \ +--epoch=194048 \ +--confirmation-enabled=false +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +cat /home/user/data/wd/node0/secrets/ | /home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --validator=/home/user/data/wd/node0/validators//keystore.json \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Nimbus VC container. It copies all files and directories from the keystore path `/home/user/data/charon` to the newly created `/home/user/data/wd` directory. The directory referenced here as `/home/user/data/node0/` is the data directory specified on start of Nimbus. [As an example in CDVC](https://github.com/ObolNetwork/charon-distributed-validator-cluster/blob/4faf38a1fc20ad241a2672021b32c90bf7ac9eb9/nimbus/run.sh#L40) the `/home/user/data/node2/` and `/home/user/data/node5/` are used. + +```sh +docker exec -it charon-distributed-validator-node-nimbus-1 /bin/bash -c "\ +mkdir -p /home/user/data/wd; \ +cp -r /home/user/data/node0/ /home/user/data/wd/; \ +/home/user/nimbus_beacon_node deposits exit \ + --rest-url=http://charon:3600/ \ + --all \ + --epoch=194048 \ + --data-dir=/home/user/data/wd/node0/;" +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--pubkeys= \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + +Replace `` with the partial pubkey found in the keystores in `.charon/validator_keys/`, under `pubkey` field. To which full pubkey a partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command signs partial exits for all validator pubkeys and broadcast them instantaneously as soon as a full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lodestar-1 node /usr/app/packages/cli/bin/lodestar validator voluntary-exit \ +--beaconNodes="http://charon:3600" \ +--network=mainnet \ +--exitEpoch=194048 \ +--dataDir=/opt/data \ +--yes +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +**Step 1: Submit partial exit** + +:::info +Lighthouse VC cannot perform an exit for custom epoch and always uses the current one. This means you should coordinate your efforts between cluster peers, in order to sign the same payload. If you sign exit messages in different epochs, signatures will not be aggregated as they will missmatch and new signing of exit messages needs to be done. +::: + + + +Following command signs a partial exit for a specific validator pubkey and broadcasts it instantaneously as soon as full exit can be created. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +file="/opt/charon/keys/keystore-.json"; \ +filename=$(basename $file); +keystore=${filename%.*}; +lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait;' +``` + +Replace `` with the keystore index. Keystore indeces can be found in `.charon/validator_keys/`. Each JSON file has a `pubkey` field corresponding to the partial pubkey. To which full pubkey this partial pubkey corresponds (as visible in Ethereum), can be looked up in the `.charon/cluster-lock.json`, under `distributed_validators` field. + + + +Following command executes an interactive command inside the Lighthouse VC container. + +```sh +docker exec -it charon-distributed-validator-node-lighthouse-1 /bin/bash -c '\ +for file in /opt/charon/keys/*; do \ + filename=$(basename $file); + if [[ $filename == *".json"* ]]; then + keystore=${filename%.*}; + lighthouse account validator exit \ + --beacon-node http://charon:3600 \ + --keystore /opt/charon/keys/$keystore.json \ + --network mainnet \ + --password-file /opt/charon/keys/$keystore.txt \ + --no-confirmation \ + --no-wait; + fi; +done;' +``` + + + +**Step 2: Monitor partial exit for all active validators** + +Consult the examples below and compare them to your validator's monitoring to verify that exits from each operator in the cluster are being received. This example is a cluster of 4 nodes with 2 validators and threshold of 3 nodes broadcasting exits are needed. + +1. Operator 1 broadcasts an exit on validator client 1. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-01-7266f9324d942a47c7966bf2f036f167.png) + + ![](https://docs.obol.org/assets/images/DutyExit-01-cc29cb51c323e290f8ceec9c0256f574.png) +2. Operator 2 broadcasts an exit on validator client 2. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-02-9592e27d4d27ab70911856badffa662a.png) + + ![](https://docs.obol.org/assets/images/DutyExit-02-560e45e9e4064f1ca26a0386f8d7ec16.png) +3. Operator 3 broadcasts an exit on validator client 3. + + ![](https://docs.obol.org/assets/images/ExitPromQuery-03-d2adbd3dec918750799fe3f07309bed3.png) + + ![](https://docs.obol.org/assets/images/DutyExit-03-12edb85f9744e0ff91264177f37fb753.png) + +At this point, the threshold of 3 has been reached and the validator exit process will start. The logs will show the following: + +![](https://docs.obol.org/assets/images/ExitLogs-04a7bf322d265372eac30d3671bd916b.png) + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + +Currently voluntary exits through Prysm are not supported. This is because [Prysm support voluntary exits only if both the validator client and the beacon node are running on Prysm](https://docs.prylabs.network/docs/wallet/exiting-a-validator). Note that this is incompatible with Charon, as the Charon client intercepts the communication between the validator client and the consensus layer. + + + +**Exit a distributed validator using DappNode** + +1. Navigate to the config tab of your Obol DappNode package. Click 'Packages', then click 'My Packages', and enter the Obol package. Go to the config tab. At the bottom right corner of the page, click on 'Show Advanced Editor'. + + ![](https://docs.obol.org/img/ConfigTabExit.png) +2. The advanced editor config page provides ENV configs for each validator. Scroll to the validator number you want to exit and type “true” in the column opposite SIGN\_EXIT. + + ![](https://docs.obol.org/img/TypeTrue.png) +3. Scroll to the bottom of the page and click the 'update' button for the changes to take effect. + + ![](https://docs.obol.org/img/ExitUpdate.png) +4. Check your logs to confirm the exit process has started. + +:::tip +Once a validator has broadcasted an exit message, it must continue to validate for at least 27 hours or longer. Do not shut off your distributed validator nodes until your validator is fully exited. +::: + + + + + +### Exit epoch and withdrawable epoch {#exit-epoch-and-withdrawable-epoch} +The process of a validator exiting from staking takes variable amounts of time, depending on how many others are exiting at the same time. + +Immediately upon broadcasting a signed voluntary exit message, the exit epoch and withdrawable epoch values are calculated based off the current epoch number. These values determine exactly when the validator will no longer be required to be online performing validation, and when the validator is eligible for a full withdrawal respectively. + +1. Exit epoch - epoch at which your validator is no longer active, no longer earning rewards, and is no longer subject to slashing rules. + +:::warning +Up until this epoch (while "in the queue") your validator is expected to be online and is held to the same slashing rules as always. Do not turn your DV node off until this epoch is reached. +::: + +2. Withdrawable epoch - epoch at which your validator funds are eligible for a full withdrawal during the next validator sweep. This occurs 256 epochs after the exit epoch, which takes \~27.3 hours. diff --git a/versioned_docs/version-v1.9/run-a-dv/running/monitoring.md b/versioned_docs/version-v1.9/run-a-dv/running/monitoring.md new file mode 100644 index 0000000000..d13b696fdd --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/monitoring.md @@ -0,0 +1,89 @@ +--- +description: "Add monitoring credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Monitoring Your Node" +slug: /run-a-dv/running/monitoring +--- + +# Monitoring Your Node + +This comprehensive guide will assist you in effectively monitoring your Charon clusters and setting up alerts by running your own Prometheus and Grafana server. If you want to use Obol’s [public dashboard](https://grafana.monitoring.gcp.obol.tech/d/d895e47a-3c2d-46b7-9b15-8f31202681af/clusters-aggregate-view?orgId=6) instead of running your servers, refer to [this section](../start/obol-monitoring.mdx) in Obol docs that teaches you how to push Prometheus metrics to Obol. + +To explain quickly, Prometheus generates the metrics and Grafana visualizes them. To learn more about Prometheus and Grafana, visit [here](https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/). If you are using [**CDVN repository**](https://github.com/ObolNetwork/charon-distributed-validator-node) or [**CDVC repository**](https://github.com/ObolNetwork/charon-distributed-validator-cluster), then Prometheus and Grafana are part of docker compose file and will be installed when you run `docker compose up`. + +The local Grafana server will have a few pre-built dashboards: + +1. Charon Overview + + This is the main dashboard that provides all the relevant details about the Charon node, for example - peer connectivity, duty completion, health of beacon node and downstream validator, etc. To open, navigate to `charon-distributed-validator-node` directory and open the following `uri` in the browser `http://localhost:3000/d/charonoverview/`. +2. Single Charon Node Dashboard (deprecated) + + This is an older dashboard Charon node monitoring which is now deprecated. If you are still using it, we would highly recommend to move to Charon Overview for most up to date panels. +3. Charon Log Dashboard + + This dashboard can be used to query the logs emitted while running your Charon node. It utilises [Grafana Loki](https://grafana.com/oss/loki/). This dashboard is not active by default and should only be used in debug mode. Refer to [advanced docker config](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md) section on how to set up a debug mode. + +| Alert Name | Description | Troubleshoot | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ClusterBeaconNodeDown | This alert is activated when the beacon node in a the cluster is offline. The beacon node is crucial for validating transactions and producing new blocks. Its unavailability could disrupt the overall functionality of the cluster. | Most likely data is corrupted. Wipe data from the point you know data was corrupted and restart beacon node so it can be synced again. | +| ClusterMissedAttestations | This alert indicates that there have been missed attestations in the cluster. Missed attestations may suggest that validators are not operating correctly, compromising the security and efficiency of the cluster. | This alert is triggered when 3 attestations are missed in 2 minutes. Check if the minimum threshold of peers are online. If correct, check for beacon node API errors and downstream validator errors using Loki. Lastly, debug from Docker using `docker compose debug`. | +| ClusterInUnknownStatus | This alert is designed to activate when a node within the cluster is detected to be in an unknown state. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` metric is 0. | This is most likely a bug in Charon. Report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| ClusterInsufficientPeers | This alert is set to activate when the number of peers for a node in the cluster is insufficient. The condition is evaluated by checking whether the maximum of the `app_monitoring_readyz` equals 4. | If you are running group cluster, check with other peers to troubleshoot the issue. If you are running solo cluster, look into other machines running the DVs to find the problem. | +| ClusterFailureRate | This alert is activated when the failure rate of the cluster exceeds a certain threshold, more specifically - more than 5% failures in duties in the last 6 hours. | Check the upstream and downstream dependencies, latency and hardware issues. | +| ClusterVCMissingValidators | This alert is activated if any validators in the cluster are missing. This happens when validator client cannot load validator keys in the past 10 minutes. | Find if validator keys are missing and load them. | +| ClusterHighPctFailedSyncMsgDuty | This alert is activated if a high percentage of sync message duties failed in the cluster. The alert is activated if the sum of the increase in failed duties tagged with "sync\_message" in the last hour divided by the sum of the increase in total duties tagged with "sync\_message" in the last hour is greater than 10%. | This may be due to limitations in beacon node performance on nodes within the cluster. In charon, this duty is the most demanding, however, an increased failure rate does not impact rewards. | +| ClusterNumConnectedRelays | This alert is activated if the number of connected relays in the cluster falls to 0. | Make sure correct relay is configured. If you still get the error report to us via [Discord](https://discord.com/channels/849256203614945310/970759460693901362). | +| PeerPingLatency | This alert is activated if the 90th percentile of the ping latency to the peers in a cluster exceeds 400ms within 2 minutes. | Make sure to set up stable and high speed internet connection. If you have geographically distributed nodes, make sure latency does not go over 250 ms. | +| ClusterBeaconNodeZeroPeers | This alert is activated when beacon node cannot find peers. | Go to docs of beacon node client to troubleshoot. Make sure there is no port overlap and p2p discovery is open. | + +## Setting Up a Contact Point + +When alerts are triggered, they are routed to contact points according notification policies. For this, contact points must be added. Grafana supports several kind of contact points like email, PagerDuty, Discord, Slack, Telegram etc. This document will teach how to add Discord channel as contact point. + +1. On left nav bar in Grafana console, under `Alerts` section, click on contact points. +2. Click on `+ Add contact point`. It will show the following page. Choose Discord in the `Integration` drop down. + + ![](/img/gitbook/image-26.png) +3. Give a descriptive name to the alert. Create a channel in Discord and copy its `webhook url`. Once done, click `Save contact point` to finish. +4. When the alerts are fired, it will send without filling in the variables for cluster detail. For example, `cluster_hash` variable is missing here `cluster_hash = {{.cluster_hash}}`. This is done to save disk space. To find the details, use `docker compose -f docker-compose.yml -f compose-debug.yml up`. More description [**here**](../../advanced-and-troubleshooting/advanced/adv-docker-configs.md). + +## Best Practices for Monitoring Charon Nodes & Cluster + +* **Establish Baselines**: Familiarize yourself with the normal operation metrics like CPU, memory, and network usage. This will help you detect anomalies. +* **Define Key Metrics**: Set up alerts for essential metrics, encompassing both system-level and Charon-specific ones. +* **Configure Alerts**: Based on these metrics, set up actionable alerts. +* **Monitor Network**: Regularly assess the connectivity between nodes and the network. +* **Perform Regular Health Checks**: Consistently evaluate the status of your nodes and clusters. +* **Monitor System Logs**: Keep an eye on logs for error messages or unusual activities. +* **Assess Resource Usage**: Ensure your nodes are neither over- nor under-utilized. +* **Automate Monitoring**: Use automation to ensure no issues go undetected. +* **Conduct Drills**: Regularly simulate failure scenarios to fine-tune your setup. +* **Update Regularly**: Keep your nodes and clusters updated with the latest software versions. + +## Third-Party Services for Uptime Testing + +* [updown.io](https://updown.io/) +* [Grafana synthetic Monitoring](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) + +## Key metrics to watch to verify node health based on jobs + +**CPU Usage**: High or spiking CPU usage can be a sign of a process demanding more resources than it should. + +**Memory Usage**: If a node is consistently running out of memory, it could be due to a memory leak or simply under-provisioning. + +**Disk I/O**: Slow disk operations can cause applications to hang or delay responses. High disk I/O can indicate storage performance issues or a sign of high load on the system. + +**Network Usage**: High network traffic or packet loss can signal network configuration issues, or that a service is being overwhelmed by requests. + +**Disk Space**: Running out of disk space can lead to application errors and data loss. + +**Uptime**: The amount of time a system has been up without any restarts. Frequent restarts can indicate instability in the system. + +**Error Rates**: The number of errors encountered by your application. This could be 4xx/5xx HTTP errors, exceptions, or any other kind of error your application may log. + +**Latency**: The delay before a transfer of data begins following an instruction for its transfer. + +It is also important to check: + +* NTP clock skew; +* Process restarts and failures (eg. through `node_systemd`); +* Alert on high error and panic log counts. diff --git a/versioned_docs/version-v1.9/run-a-dv/running/request-withdrawal.md b/versioned_docs/version-v1.9/run-a-dv/running/request-withdrawal.md new file mode 100644 index 0000000000..8116aea479 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/request-withdrawal.md @@ -0,0 +1,138 @@ +--- +description: "Learn how to request withdrawals from validators with 0x02 withdrawal credentials using OVM, including batching and principal/rewards distinction." +sidebar_label: "Request Withdrawal" +slug: /run-a-dv/running/request-withdrawal +--- + +# Request Withdrawal + +Post-Pectra update, a new type of validator with 0x02 withdrawal credentials type are supported that can have more than 32 ETH of effective balance. Unlike the validators with a `0x01` withdrawal credentials type, which go through periodic skimming of their consensus rewards through a withdrawal sweep, `0x02` rewards are added to the balance to enable auto-compounding. As a result, there is no automatic skimming of rewards. Users have to explicitly send a transaction to request a withdrawal of their rewards to the beacon chain. OVM simplifies requesting a withdrawal by: + +1. Supporting batching of withdrawal requests across multiple validators +2. Helping users distinguish between rewards and principal as long as all deposits are done through OVM's and reward amounts are below the principal threshold + +The following steps guide you through how to request a withdrawal from your validators: + +## Step-by-Step Withdrawal Process + +1. On the cluster details page, go to the validators table. In the actions column, click on the withdraw icon. If the withdrawal address is an OVM, the connected address must have the `WITHDRAWAL_ROLE` to request a withdrawal. If the withdrawal address is an EOA, make sure you are connected with the correct EOA. **Read more about how to assign roles** [**here**](../../advanced-and-troubleshooting/advanced/assign-ovm-roles.md)**.** + +![](/img/gitbook/OVMWithdrawalButton.png) + +1. If the user has sufficient permissions, the withdrawal address is an EOA or an OVM, and the validator is with `0x02` withdrawal credentials, a modal opens allowing the user to specify the total withdrawal amount. The fields in this modal mean the following: + 1. **Validator Balance:** Total balance of all validators under this OVM or EOA + 2. **Withdrawal Limit:** The maximum amount a user can withdraw without triggering an exit. For example, if the validator balance is 100 ETH and 2 validators are active, the withdrawal limit is 100 - (2 × 32) = 36 ETH + +:::info +💡 When deciding the amount to withdraw, users must pay attention to the amount of ETH in their OVM's balance, pending withdrawals and OVM's principal threshold. These fields together help decide how much to withdraw to reach the principal threshold. Read more about this in the [FAQ section](request-withdrawal.md#3-how-to-decide-initial-withdrawal-amount). +::: + +![](/img/gitbook/WithdrawalAmountEntered.png) + +3. Once an amount has been selected, the UI recommends how the withdrawal amount should be split across validators. Read more in the [FAQ section](request-withdrawal.md#2-how-recommendation-for-requesting-withdrawal-works). If you would prefer to allocate specific amounts manually, click on `Allocate Manually`. + +![](/img/gitbook/OVMWithdrawal3.png) + +4. For manually allocating, users must stay below the withdrawal limit. Users can also choose to exit a validator by withdrawing its entire available balance. + +![](/img/gitbook/OVMWithdrawal4.png) + +5. Before you confirm, review the post-withdrawal balances of the validators and whether any validators will exit. Upon confirmation, withdrawal request transactions are sent. Once the transaction is accepted, the validator enters the queue awaiting a withdrawal sweep. The waiting period depends on the validator’s position in the current withdrawal queue. + +## FAQ + +### 1. Why can I not see the ETH in my wallet after I sent a withdrawal request? + +If you have successfully sent a transaction to the Ethereum Withdrawal Contract to trigger a partial withdrawal or an exit for your **0x02 validator**, but the ETH is not yet in your wallet, it is usually due to one of the following protocol-level steps. + +#### 1. Is your request still in the Partial Withdrawal Queue"? + +Unlike older 0x01 validators that are automatically "swept" by the protocol, 0x02 withdrawals are **triggered manually** and therefore enter a First-In-First-Out (FIFO) queue. + +* **The Delay:** If many stakers are withdrawing at once, your request must wait its turn. +* **How to check:** Visit a block explorer like [beaconcha.in](https://beaconcha.in/) and look for the **"Partial Withdrawal Queue"** status. + +#### 2. Are you in the "27-Hour Cooldown" period? + +Every withdrawal request—even after it clears the initial queue—is subject to a mandatory security delay. + +* **The Delay:** Approximately **27 hours and 50 minutes** (256 epochs). +* **Why?** This is a safety protocol to prevent rapid "stake-grinding" attacks and ensure network stability. Your ETH will remain on the validator and **continue earning rewards** during this specific window. + +#### 3. Did you leave at least 32 ETH in the validator? + +For 0x02 validators, you can only withdraw the "excess" balance. + +* **The Rule:** You cannot partially withdraw a validator's balance below **32 ETH** while keeping it active. If you requested an amount that would drop your balance below 32 ETH, the protocol may reject the request or only process the amount available above the 32 ETH limit. + +#### 4. Is the network experiencing a "Mass Exit" or "High Churn"? + +If you are performing a **Full Exit** and not just a partial withdrawal, you are subject to the **Churn Limit**. + +* **The Delay:** Ethereum only allows a certain amount of ETH (approximately 256 ETH per epoch) to exit the network at once. During periods of high volatility or institutional exits, this queue can stretch from a few days to **several weeks**. +* **0x01 vs 0x02:** While 0x02 partial withdrawals are usually faster because they skip the "sweep cycle," full exits for both 0x01 and 0x02 validators remain in the same global exit line. + +#### 5. Are you checking the right "Arrival" type? + +Withdrawals do not arrive as a standard "Transfer" transaction. + +* **What to look for:** ETH withdrawals are **"Balance Increases"** provided directly by the protocol. They will appear in the **"Withdrawals"** tab of your address on a block explorer, rather than the "Transactions" or "Internal Txns" tab. Your wallet balance will increase, but you may not see a "Received" notification in some apps. + +### 2. How recommendation for requesting withdrawal works? + +The recommended approach is to withdraw ETH from the active validator that has the **lowest current ETH balance** until that validator's withdrawal limit is reached. + +| **Scenario** | **Example** | **Recommendation** | +| -------------- | -------------------- | ------------------------------------------- | +| **Goal** | Withdraw 10 ETH | Withdraw 10 ETH from the 100 ETH validator. | +| **Validators** | Validator A: 100 ETH | **NOT** the 200 ETH validator. | +| | Validator B: 200 ETH | | + +While the difference in rewards is usually minimal, this strategy helps to **optimize the effective balance** of your highest-earning validator: + +* **Effective Balance:** Validator rewards are calculated based on the "effective balance," which is rounded down to the nearest whole ETH, capped at 32 ETH. The protocol has a **0.5 ETH hysteresis limit** for rounding to the _next_ whole integer. For example, a validator must reach **32.5 ETH** to be treated as having a 33 ETH effective balance (capped at 32 ETH). +* **The Goal:** By withdrawing from the validator with **less ETH**, you ensure the higher-balance validator (the **200 ETH** one in your example) keeps as much stake as possible. Since the 200 ETH validator is already earning more rewards, keeping its balance high gives it the best chance to quickly cross the next **0.5 ETH threshold** needed to potentially boost its effective balance (and therefore its rewards) sooner. + +### 3. How to decide initial withdrawal amount? + +When initiating a withdrawal, the OVM (Obol Validator Manager) uses the **Principal Threshold** (Tp) to determine whether the withdrawn ETH will be classified as **Principal** or **Rewards** upon the next distribution event. + +The key calculation users must understand is the **Projected OVM Balance**—the total ETH that will reside in the OVM once all current and pending transactions are complete. The amount you input in the withdrawal field is the only variable you can control to govern this outcome. Based on your input, the UI provides warnings indicating where the withdrawal will be routed once it succeeds. + +#### Core Withdrawal Principle + +The decision is based on a comparison between the **Projected OVM Balance** and the **Principal Threshold** (Tp). + +**Projected OVM Balance = B\_ovm + W\_pending + W\_current** + +Where: + +* **B\_ovm:** Current OVM Balance (ETH already in the contract). +* **W\_pending:** Pending Withdrawals (ETH from previous successful transactions that are known to be en route to the OVM). +* **W\_current:** Currently Withdrawing amount (the value the user is inputting). +* **Tp:** Principal Threshold (a fixed ETH value). + +#### The Distribution Rules + +The OVM classifies the withdrawal based on the **Projected OVM Balance**: + +| **Condition** | **Formula (Plain Text)** | **Outcome (Upon Distribution)** | **Destination** | +| ------------------------------------------- | -------------------------------------- | --------------------------------------- | ------------------------------------ | +| **Principal Rule** (Threshold Met/Exceeded) | B\_ovm + W\_pending + W\_current >= Tp | The amount is treated as **Principal**. | Sent to the **Principal Recipient**. | +| **Rewards Rule** (Below Threshold) | B\_ovm + W\_pending + W\_current < Tp | The amount is treated as **Rewards**. | Sent to the **Reward Recipient(s)**. | + +#### Example + +Assume **Tp = 16 ETH**, **B\_ovm = 10 ETH**, and **W\_pending = 2 ETH**. The current base is 10 + 2 = 12 ETH. + +| **Withdrawal Amount (W\_current)** | **Projected OVM Balance** | **Result** | **Destination** | +| ---------------------------------- | ------------------------- | ------------------------------------- | ------------------- | +| **4 ETH** (or more) | 10 + 2 + 4 = 16 ETH | 16 ETH >= 16 ETH **(Principal Rule)** | Principal Recipient | +| **3 ETH** (or less) | 10 + 2 + 3 = 15 ETH | 15 ETH < 16 ETH **(Rewards Rule)** | Reward Recipient(s) | + +#### Action for Rewards Recipients + +If the withdrawal is classified as Rewards: + +* **Splitter Contract:** The distribution will trigger a function in the splitter to share the rewards among the configured addresses. +* **EOA (Externally Owned Account):** The amount will be sent directly to the EOA address. diff --git a/versioned_docs/version-v1.9/run-a-dv/running/update-a-dv.mdx b/versioned_docs/version-v1.9/run-a-dv/running/update-a-dv.mdx new file mode 100644 index 0000000000..a83806a2fa --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/running/update-a-dv.mdx @@ -0,0 +1,129 @@ +--- +sidebar_label: "Update a DV" +slug: /run-a-dv/running/update-a-dv +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Update a DV + +It is highly recommended to upgrade your DV stack from time to time. This ensures that your node is secure, performant, up-to-date and you don't miss important hard forks. + +To do this, follow these steps: + + + +```sh +cd charon-distributed-validator-node +``` + +**Pull latest changes to the repo** + +```sh +git pull +``` + +**Create (or recreate) your DV stack** + +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +**Conflicts** + +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + + +```sh +cd charon-distributed-validator-cluster +``` + +**Pull latest changes to the repo** + +```sh +git pull +``` + +**Create (or recreate) your DV stack** + +```sh +docker compose up -d --build +``` + +:::danger +If you run more than one node in a DV Cluster, please take caution upgrading them simultaneously. Particularly if you are updating or changing the validator client used or recreating disks. It is recommended to update nodes on a sequential basis to minimise liveness and safety risks. +::: + +**Conflicts** + +You may get a `git conflict` error similar to this: + +```sh +error: Your local changes to the following files would be overwritten by merge: +prometheus/prometheus.yml + +Please commit your changes or stash them before you merge. +``` + +This is probably because you have made some changes to some of the files, for example to the `prometheus/prometheus.yml` file. + +To resolve this error, you can either: + +* Stash and reapply changes if you want to keep your custom changes: + + ```sh + git stash # Stash your local changes + git pull # Pull the latest changes + git stash apply # Reapply your changes from the stash + docker-compose up -d --build # Recreate your DV stack + ``` + + After reapplying your changes, manually resolve any conflicts that may arise between your changes and the pulled changes using a text editor or Git's conflict resolution tools. +* Override changes and recreate configuration if you don't need to preserve your local changes and want to discard them entirely: + + ```sh + git reset --hard # Discard all local changes and override with the pulled changes + git pull # Pull the latest changes + docker-compose up -d --build # Recreate your DV stack + ``` + + After overriding the changes, you will need to recreate your DV stack using the updated files. By following one of these approaches, you should be able to handle Git conflicts when pulling the latest changes to your repository, either preserving your changes or overriding them as per your requirements. + + diff --git a/versioned_docs/version-v1.9/run-a-dv/start/README.md b/versioned_docs/version-v1.9/run-a-dv/start/README.md new file mode 100644 index 0000000000..170adf3c16 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/start/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Quickstart" +slug: /run-a-dv/start +--- + +# Quickstart + diff --git a/versioned_docs/version-v1.9/run-a-dv/start/create-a-dv-alone.mdx b/versioned_docs/version-v1.9/run-a-dv/start/create-a-dv-alone.mdx new file mode 100644 index 0000000000..0f9862e9e9 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/start/create-a-dv-alone.mdx @@ -0,0 +1,201 @@ +--- +sidebar_label: "Create a DV Alone" +slug: /run-a-dv/start/create-a-dv-alone +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV Alone + +:::info +It is possible for a single operator to manage all of the nodes of a DV cluster. The nodes can be run on a single machine, which is only suitable for testing, or the nodes can be run on multiple machines, which is expected for a production setup. + +The private key shares can be created centrally and distributed securely to each node. Alternatively, the private key shares can be created in a lower-trust manner with a [Distributed Key Generation](../../learn/intro/key-concepts.md#distributed-validator-key-generation-ceremony) process, which avoids the validator private key being stored in full anywhere, at any point in its lifecycle. Follow the [group quickstart](create-a-dv-with-a-group.mdx) instead for this latter case. +::: + +### Pre-requisites {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* Ensure you have [git](https://git-scm.com/downloads) installed. +* Ensure you have [docker](https://docs.docker.com/engine/install/) installed. +* Make sure `docker` is running before executing the commands below. + +### Step 1: Create the key shares locally {#step-1-create-the-key-shares-locally} + + +Go to the [DV Launchpad](../../learn/intro/launchpad.md) and select `Create a distributed validator alone`. Follow the steps to configure your DV cluster. The Launchpad will give you a docker command to create your cluster.\ +Before you run the command, clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster.git) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ + +# Run the command provided in the DV Launchpad "Create a cluster alone" flow +docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.9.0 create cluster --definition-file=... + +``` + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +1. Clone the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster) and `cd` into the directory. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-cluster.git + +# Change directory +cd charon-distributed-validator-cluster/ +``` + +2. Run the cluster creation command, setting required flag values. + +Run the below command to create the validator private key shares and cluster artifacts locally, replacing the example values for `nodes`, `network`, `num-validators`, `fee-recipient-addresses`, and `withdrawal-addresses`. Check the [Charon CLI reference](../../learn/charon/charon-cli-reference.md#create-a-full-cluster-locally) for additional, optional flags to set. + +```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 create cluster \ + --nodes=6 \ + --network=hoodi \ + --num-validators=1 \ + --name="Quickstart Guide Cluster" \ + --cluster-dir="cluster" \ + --fee-recipient-addresses=0x000000000000000000000000000000000000dead \ + --withdrawal-addresses=0x000000000000000000000000000000000000dead \ + --publish +``` + +:::tip +If you would like your cluster to appear on the [DV Launchpad](../../learn/intro/launchpad.md), add the `--publish` flag to the command. +::: + +After the `create cluster` command is run, you should have multiple subfolders within the newly created `./cluster/` folder, one for each node created. + +**Backup the `./cluster/` folder, then move on to deploying the cluster.** + +:::info +Make sure your backup is secure and private, someone with access to these files could get the validators slashed. +::: + + + +### Step 2: Deploy and start the nodes {#step-1-create-the-key-shares-locally} + + +:::warning +This part of the guide only runs one Execution Client, one Consensus Client, and 6 Distributed Validator Charon Client + Validator Client pairs on a single docker instance, and **is not suitable for a mainnet deployment**. (If this machine fails, there will not be any fault tolerance - the cluster will also fail.) + +For a production deployment with fault tolerance, follow the part of the guide instructing you how to distribute the nodes across multiple machines. +::: + +Run this command to start your cluster containers if you deployed using the [CDVC repo](https://github.com/ObolNetwork/charon-distributed-validator-cluster). + +```sh +# Start the distributed validator cluster +docker compose up --build -d +``` + +Check the monitoring dashboard and see if things look all right. + +```sh +# Open Grafana +open http://localhost:3000/d/laEp8vupp +``` + + + +:::warning +To distribute your cluster across multiple machines, each node in the cluster needs one of the folders called `node*/` to be copied to it. Each folder should be copied to a [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) and renamed from `node*` to `.charon`. + +Right now, the `charon create cluster` command [used earlier to create the private keys](create-a-dv-alone.mdx#step-1-create-the-key-shares-locally) outputs a folder structure like `cluster/node*/`. Make sure to grab the `./node*/` folders, _rename_ them to `.charon` and then move them to one of the single node repos below. Once all nodes are online, synced, and connected, you will be ready to activate your validator. +::: + +This is necessary for the folder to be found by the default `charon run` command. Optionally, it is possible to override `charon run`'s default file locations by using `charon run --private-key-file="node0/charon-enr-private-key" --lock-file="node0/cluster-lock.json"` for each instance of Charon you start (substituting `node0` for each node number in your cluster as needed). + +👉 Use the single node [docker compose](https://github.com/ObolNetwork/charon-distributed-validator-node), the kubernetes [manifests](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node), or the [helm chart](https://github.com/ObolNetwork/helm-charts) example repos to get your nodes up and connected after loading the `.charon` folder artifacts into them appropriately. + +Output from create cluster: + +``` +cluster +├── node0 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node1 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +├── node2 +│ ├── charon-enr-private-key +│ ├── cluster-lock.json +│ ├── deposit-data.json +│ └── validator_keys +│ ├── keystore-0.json +│ ├── keystore-0.txt +│ ├── ... +│ ├── keystore-N.json +│ └── keystore-N.txt +└── node3 + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt + +``` + +Folder structure to be placed on each DV node: + +``` +└── .charon + ├── charon-enr-private-key + ├── cluster-lock.json + ├── deposit-data.json + └── validator_keys + ├── keystore-0.json + ├── keystore-0.txt + ├── ... + ├── keystore-N.json + └── keystore-N.txt +``` + +:::info +Currently, the quickstart repo installs a node on the Hoodi testnet. It is possible to choose a different network (another testnet, or mainnet) by overriding the `.env` file. + +`.env.sample` is a sample environment file that allows overriding default configuration defined in `docker-compose.yml`. Uncomment and set any variable to override its value. + +Set up the desired inputs for the DV, including the network you wish to operate on. Check the [Charon CLI reference](../../learn/charon/charon-cli-reference.md) for additional optional flags to set. Once you have set the values you wish to use. Make a copy of this file called `.env`. + +```sh +# Copy ".env.sample", renaming it ".env" +cp .env.sample .env +``` +::: + + diff --git a/versioned_docs/version-v1.9/run-a-dv/start/create-a-dv-with-a-group.mdx b/versioned_docs/version-v1.9/run-a-dv/start/create-a-dv-with-a-group.mdx new file mode 100644 index 0000000000..b6d4273f37 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/start/create-a-dv-with-a-group.mdx @@ -0,0 +1,701 @@ +--- +description: "This quickstart guide will walk you through creating a Distributed Validator Cluster with a number of other node operators." +sidebar_label: "Create a DV With a Group" +slug: /run-a-dv/start/create-a-dv-with-a-group +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Create a DV With a Group + +### Pre-requisites {#pre-requisites} +* A basic [knowledge](https://docs.ethstaker.cc/ethstaker-knowledge-base/) of Ethereum nodes and validators. +* A machine that meets the [minimum requirements](../prepare/deployment-best-practices.md#hardware-specifications) for the network you intend to validate. +* If you are taking part using a [DappNode](https://dappnode.com/): + * A computer with an up to date version of [DappNode](https://docs.dappnode.io/docs/user/install/overview/)'s software and an internet connection. +* If you are taking part using [Sedge](https://www.nethermind.io/sedge), or [Charon's Distributed Validator Node](https://github.com/ObolNetwork/lido-charon-distributed-validator-node) (CDVN) starter repo: + * Ensure you have [git](https://git-scm.com/downloads) installed. + * Ensure you have [docker](https://docs.docker.com/engine/install/) installed. + * Make sure `docker` is running before executing the commands below. + +### Step 1: Get your ENR {#step-1-get-your-enr} + + +In order to prepare for a distributed key generation ceremony, you need to create an ENR for your Charon client. This ENR is a public/private key pair that allows the other Charon clients in the DKG to identify and connect to your node. If you are creating a cluster but not taking part as a node operator in it, you can skip this step. + +```sh +# Clone the repo +git clone https://github.com/ObolNetwork/charon-distributed-validator-node.git +# Change directory +cd charon-distributed-validator-node/ +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 create enr +``` + +You should expect to see a console output like this: + +```sh +Created ENR private key: .charon/charon-enr-private-key +enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u +``` + +:::warning +Please make sure to create a backup of the private key at `.charon/charon-enr-private-key` Be careful not to commit it to git! **If you lose this file you won't be able to take part in the DKG ceremony nor start the DV cluster successfully.** +::: + +:::tip +If instead of being shown your `enr` you see an error saying `permission denied` then you may need to [update your docker permissions](../../advanced-and-troubleshooting/troubleshooting/errors.md#how-to-fix-permission-denied-errors) to allow the command to run successfully. +::: + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Prepare an Execution and Consensus client** + +Before preparing the DappNode to take part in a Distributed Validator Cluster, you must ensure you have selected an execution client & consensus client on your DappNode under the 'Stakers' tab for the network you intend to validate. + +1. Login to the DappNode Interface: + + ![](/img/gitbook/image-58.png) +2. Click on the 'Stakers' tab on the left side, select an execution client (e.g. Geth) & consensus client (e.g. Lodestar) & click 'Apply changes'. This will start the syncing process which can take a number of hours. + + ![](/img/gitbook/image-64.png) +3. Once the clients are finished syncing, it should reflect on your 'Dashboard' as shown below. + + ![](/img/gitbook/image-65.png) + +**Install the Obol DappNode package** + +With a fully synced Ethereum node now running on the DappNode, the below steps will walk through installing the Obol package via an IPFS hash and preparing for a Distributed Key Generation ceremony. Future versions of this guide will download the package from the official DappNode DappStore once a stable 1.0 release is made. + +1. Before installing the package, make sure you are installing the correct one, this depends on which network your creator configures the cluster on, Holesky or Mainnet. You can find the link to both packages below: + * [Holesky Repo](http://my.dappnode/installer/dnp/holesky-obol.dnp.dappnode.eth) + * [Mainnet Repo](http://my.dappnode/installer/dnp/obol.dnp.dappnode.eth) +2. Copy the latest IPFS hash from the release details dropdown. + + ![](/img/gitbook/image-66.png) +3. Go back to DappNode Dashboard > Dappstore, select the 'Public' tab, and accept the terms & conditions before proceeding. + + ![](/img/gitbook/image-68.png) +4. Paste the IPFS hash you copied from Github and click 'Search' (It may take a minute for the package to be found.) You will then be presented with the package installation page. Under the blue 'Install' button, click on 'Advanced Options' & toggle the button to 'Bypass only signed safe restriction'. + + ![](/img/gitbook/image-69.png) +5. Click 'Install' & in the config mode page > select new cluster & submit. (if you already have the config URL, you can select URL option.) + + ![](/img/gitbook/image-70.png) +6. Accept the terms & conditions and the install process will begin. + + ![](/img/gitbook/image-71.png) + + ![](/img/gitbook/image-72.png) +7. You should now be able to see the Holesky Obol package under the 'Packages' tab. Click on the package to see important details. + + ![](/img/gitbook/image-73.png) +8. Under the 'Info' tab, you will see pre-generated ENRs, along with information such as the status of all five distributed validator clusters, their docker volumes & other menu options. + + ![](/img/gitbook/image-74.png) +9. Select any of the ENRs listed that are not already in use. This ENR will be used in the next step. + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +**Installing Sedge** + +First you must install Sedge, please refer to the [official Sedge installation guide](https://docs.sedge.nethermind.io/docs/quickstart/install-guide) to do so. + +**Check the install was successful** + +Run the below command to check if your have successfully installed sedge in your computer. + +``` +sedge +``` + +Expected output: + +```sh +A tool to allow deploying validators with ease. + Usage: + sedge [command] + Available Commands: + cli Generate a node setup interactively + clients List supported clients + deps Manage dependencies + down Shutdown sedge running containers + generate Generate new setups according to selected options + help Help about any command + import-key Import validator keys + keys Generate keystore folder + logs Get running container logs + networks List supported networks + run Run services + show Show useful information about sedge running containers + slashing-export Export slashing protection data + slashing-import Import slashing protection data + version Print sedge version + Flags: + -h, --help help for sedge + --log-level string Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace (default "info") + Use "sedge [command] --help" for more information about a command. +``` + +Create an ENR using charon: + +```sh +# Use docker to create an ENR. Backup the file `.charon/charon-enr-private-key`. +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 create enr +``` + +For Step 2 of the quickstart: + +* Select the **Creator** tab if you are coordinating the creation of the cluster (this role holds no position of privilege in the cluster, it only sets the initial terms of the cluster that the other operators agree to). +* Select the **Operator** tab if you are accepting an invitation to operate a node in a cluster, proposed by the cluster creator. + + + +### Step 2: Create a cluster or accept an invitation to a cluster {#step-2-create-a-cluster-or-accept-an-invitation-to-a-cluster} + + +**Collect addresses, configure the cluster, share the invitation** + +Before starting the cluster creation process, you will need to collect an Ethereum address for each operator in the cluster. They will need to be able to sign messages through MetaMask with this address. _(Broader wallet support will be added in future.)_ With these addresses in hand, go through the cluster creation flow. + + + +You will use the Launchpad to create an invitation, and share it with the operators. This video shows the flow within the [DV Launchpad](../../learn/intro/launchpad.md) + + + +The following are the steps for creating a cluster. + +1. Go to the [DV Launchpad](../../learn/intro/launchpad.md#dv-launchpad-links) +2. Connect your wallet + + ![](/img/gitbook/image-75.png) +3. Select `Create a Cluster with a group` then `Get Started`. + + ![](/img/gitbook/image-76.png) +4. Follow the flow and accept the advisories. +5. Configure the Cluster + 1. Input the `Cluster Name` & `Cluster Size` (i.e. number of operators in the cluster). The threshold will update automatically, it shows the number of nodes that need to be functioning for the validator(s) to stay active. +6. Input the Ethereum addresses for each operator that you collected previously. If you will be taking part as an operator, click the "Use My Address" button for Operator 1. + + 1. Select the desired amount of validators (32 ETH each) the cluster will run. + 2. If you are taking part in the cluster, enter the ENR you generated in [step one](create-a-dv-with-a-group.mdx#step-1-get-your-enr) in the "What is your charon client's ENR?" field. + 3. Choose the suitable withdrawal configuration: + + ![](/img/gitbook/WithdrawalConfigurations.png) + + * **Split only rewards**: Deploys an OVM contract as withdrawal address to a principal address of your choice, and a splitter as fee recipient. OVM is used to distribute amounts to principal and fee recipient. It requires two inputs: + * **Owner address**: The Owner address is the super-admin of the OVM. It has access to all the roles - deposit, withdraw, distribute etc and it can also give roles to other addresses. For security purposes, it is recommended to either use a trusted address or a multi-sig wallet like [SAFE](https://app.safe.global/welcome/accounts) so all the transactions are approved by a quorum of addresses inside the SAFE. For testing purposes on Hoodi, [protofire](https://app.safe.protofire.io/home) can be used. + * **Principal address**: This is the address that will receive the amount after the principal threshold amount is crossed. Read more about it [here](../../learn/intro/obol-splits.md#obol-validator-managers) where it is explained. + * **Split Everything**: Deploys an OVM contract as withdrawal address, with principal and fee recipient addresses both as splitter contracts. In this case both principal and rewards are distributed. It just requires Owner address as input which is again recommended to be a SAFE wallet. + * **Lido CSM**: Deploys the clusters with Lido's withdrawal vault as withdrawal address and execution vault as fee recipient. Read more about the process to register CSM cluster [here](../integrations/lido-csm.md). + * **Custom**: Enter the `Principal address` which should receive the principal 32 ETH and the accrued consensus layer rewards when the validator is exited. This can optionally be set to the contract address of a multisig / splitter contract. Enter the `Fee Recipient address` to which the execution layer rewards will go. This can be the same as the principal address, or it can be a different address. This can optionally be set to the contract address of a multisig / splitter contract. +7. Click `Create Cluster Configuration`. Review that all the details are correct, and press `Confirm and Sign` You will be prompted to sign two or three transactions with your MetaMask wallet. These are: + 1. The `config_hash`. This is a hashed representation of the details of this cluster, to ensure everyone is agreeing to an identical setup. + 2. The `operator_config_hash`. This is your acceptance of the terms and conditions to participate as a node operator. + 3. Your `ENR`. Signing your ENR authorises the corresponding private key to act on your behalf in the cluster. +8. Share your cluster invite link with the operators. Following the link will show you a screen waiting for other operators to accept the configuration you created. + + ![](/img/gitbook/image-77.png) +9. You can use the link to monitor how many of the operators have already signed their approval of the cluster configuration and submitted their ENR. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + +You will use the CLI to create the cluster definition file, which you will distribute it to the operators manually. + +1. The leader or creator of the cluster will prepare the `cluster-definition.json` file for the Distributed Key Generation ceremony using the `charon create dkg` command. +2. Populate the `charon create dkg` command with the appropriate flags including the `name`, the `num-validators`, the `fee-recipient-addresses`, the `withdrawal-addresses`, and the `operator-enrs` of all the operators participating in the cluster. +3. Run the `charon create dkg` command that generates DKG cluster-definition.json file. + + ```sh + docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 create dkg + + --name="Quickstart" + + --num-validators=1 + + --fee-recipient-addresses="0x0000000000000000000000000000000000000000" + + --withdrawal-addresses="0x0000000000000000000000000000000000000000" + + --operator-enrs="enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7GblVaCjL_8FKQhF6Syg-O_kIWztimGAYHY5EvPgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKzMe_GFPpSqtnYl-mJr8uZAUtmkqccsAx7ojGmFy-FY4N0Y3CCDhqDdWRwgg4u" + ``` + + This command should output a file at `.charon/cluster-definition.json` This file needs to be shared with the other operators in a cluster. + + * The `.charon` folder is hidden by default. To view it, run `ls -al .charon` in your terminal. Else, if you are on `macOS`, press `Cmd + Shift + .` to view all hidden files in the Finder application. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + + + + + +**Join the cluster prepared by the creator** + +Use the Launchpad or CLI to join the cluster configuration generated by the creator: + + + +Your cluster creator needs to configure the cluster, and send you an invite URL link to join the cluster on the Launchpad. Once you've received the Launchpad invite link, you can begin the cluster acceptance process. + + + +1. Click on the DV launchpad link provided by the leader or creator. Make sure you recognise the domain and the person sending you the link, to ensure you are not being phished. +2. Connect your wallet using the Ethereum address the leader was provided. + + ![](/img/gitbook/image-81.png) +3. Review the operators addresses submitted and click `Get Started` to continue. + + ![](/img/gitbook/image-82.png) +4. Review and accept the DV Launchpad terms & conditions and advisories. +5. Before accepting the invite and adding your ENR, ensure the following: + +

Important: Review these details carefully before proceeding. Once you accept the cluster configuration, you'll be committed to the withdrawal and fee recipient addresses set by the creator.

+ + 1. **Withdrawal address verification:** + * If the withdrawal address is an OVM (Obol Validator Manager): + 1. Make sure it has the **OVM tag** to ensure it's the correct and official version of the audited contract. + 2. Ensure the **OVM owner** is correct. If it's a SAFE contract, verify the SAFE and all addresses inside the SAFE are as expected. + 3. Verify that all **roles are assigned correctly** if required. Note that the owner can edit roles even after accepting the cluster invite. If you require roles to be permanent, ensure ownership is renounced before accepting. + * For more information on OVM roles, see the [OVM role assignment guide](../../advanced-and-troubleshooting/advanced/assign-ovm-roles.md). + 2. **Fee recipient verification:** + * If the fee recipient is a splitter contract, ensure the **percentage of fee splits are correct**. + * Just like OVM, fee recipient contracts also have an owner. Ensure that **ownership is revoked** if you want the shares to remain unchanged. +6. Review the cluster configuration set by the creator and add your `ENR` that you generated in [step 1](create-a-dv-with-a-group.mdx#step-1-get-your-enr).\\ + + ![](/img/gitbook/image-83.png) +7. Sign the two transactions with your wallet, these are: + * The config hash. This is a hashed representation of all of the details for this cluster. + * Your own `ENR` This signature authorises the key represented by this ENR to act on your behalf in the cluster. +8. Wait for all the other operators in your cluster to also finish these steps. + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. +
+ + +You'll receive the `cluster-definition.json` file created by the leader/creator. You should save it in the `.charon/` folder that was created initially. (Alternatively, you can use the `--definition-file` flag to override the default expected location for this file.) + +Once every participating operator is ready, the next step is the distributed key generation amongst the operators. + +* If you are not planning on operating a node, and were only configuring the cluster for the operators, your journey ends here. Well done! +* If you are one of the cluster operators, continue to the next step. + +
+
+
+ +### Step 3: Run the Distributed Key Generation (DKG) ceremony {#step-3-run-the-distributed-key-generation-dkg-ceremony} +:::tip +For the [DKG](../../learn/charon/dkg.md) to complete, all operators need to be running the command simultaneously. It helps if operators can agree on a certain time or schedule a video call for them to all run the command together. +::: + + + + + +1. Once all operators successfully signed, your screen will automatically advance to the next step and look like this. Click `Continue`. (If you closed the tab, you can always go back to the invite link shared by the leader and connect your wallet.) + + ![](/img/gitbook/image-1-1-1.png) +2. Copy and run the `docker` command on the screen into your terminal. It will retrieve the remote cluster details and begin the DKG process. + + ![](/img/gitbook/image-2-1.png) +3. Assuming the DKG is successful, a number of artefacts will be created in the `.charon` folder of the node. These include: + * A `deposit-data.json` file. This contains the information needed to activate the validator on the Ethereum network. + * A `cluster-lock.json` file. This contains the information needed by Charon to operate the distributed validator cluster with its peers. + * A `validator_keys/` folder. This folder contains the private key shares and passwords for the created distributed validators. + + + +Once the creator gives you the `cluster-definition.json` file and you place it in a `.charon` subdirectory, run: + +```sh +docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.9.0 dkg --publish +``` + +and the DKG process should begin. + + + +Follow this step if you are signing through the DV Launchpad, importing the cluster definition URL into the DappNode package's config & then running the DKG inside the DappNode, followed by cluster run. + +![](/img/gitbook/image-3-1.png) + +1. After all operators have signed with their wallet and has provided an ENR from the DappNode info tab, the Launchpad will instruct operators to begin the DKG ceremony. Click continue & navigate to the 'Dappnode/Avado' tab where the cluster definition URL is presented. + + ![](/img/gitbook/image-4-1.png) +2. To run the Distributed Key Generation ceremony using a DappNode, you must paste the cluster definition URL into the Obol Package interface. Go to the 'Config' tab, select 'URL' from the dropdown menu, paste the cluster definition URL you retrieved from the launchpad, into the validator `cluster-*`field which matches the cluster you took the ENR from. Example: If you picked ENR1 for signing, then you should paste the URL into Cluster-1. Finally, click the 'Update' button at the bottom of the page. + + ![](/img/gitbook/image-6-1.png) + + ![](/img/gitbook/image-7-1.png) + + ![](/img/gitbook/image-8-1.png) +3. After DappNode records the cluster definition URL, go back to the 'Info' tab and restart the Charon container. + + ![](/img/gitbook/image-9-1.png) +4. The node is now ready and will attempt to complete the DKG. You can monitor the DKG progress via the 'Logs' tab of the package. Once all clients in the cluster can establish a connection with one another and they each complete a handshake (confirm everyone has a matching `cluster_definition_hash`), the key generation ceremony begins. + + ![](/img/gitbook/image-10-1.png) +5. Example of DKG ceremony competed log. + + ![](/img/gitbook/image-11-1.png) + +**Create a DV Node Backup** + +It is important to back up all artefacts generated by the DKG ceremony, and your node ENR private key. The below steps will show you how to download your keys & node artefacts. + +1. Navigate to the backup tab inside the Obol package. + + ![](/img/gitbook/image-12-1.png) +2. Click on the 'Backup now' button and it will open a new chrome window with a 'file save' option. Select the path where you want to save the Backup tar file. + + ![](/img/gitbook/image-13-1.png) +3. Double click to extract the tar file. There will be folders for each charon node (max 5). Navigate to each node folder, and all artefacts related to each node will be present. + + ![](/img/gitbook/image-14-1.png) + + ![](/img/gitbook/image-15-1.png) + + + +Sedge does not currently support taking part in a DKG. Follow the instructions for **Launchpad** to take part in the DKG with Charon, and in Step 4 you will import these keys into Sedge. + + + +:::danger +Please make sure to create a backup of your `.charon/` folder. **If you lose your private keys you won't be able to start the DV cluster successfully and may risk your validator deposit becoming unrecoverable.** Ensure every operator has their `.charon` folder securely and privately backed up before activating any validators. +::: + +:::info +The `cluster-lock` and `deposit-data` files are identical for each operator, if lost, they can be copied from one operator to another. +::: + +Now that the DKG has been completed, all operators can start their nodes. + +### Step 4: Start your Distributed Validator Node {#step-4-start-your-distributed-validator-node} +With the DKG ceremony over, the last phase before activation is to prepare your node for validating over the long-term. + +The [CDVN repository](https://github.com/ObolNetwork/charon-distributed-validator-node) is configured to sync an execution layer client (`Nethermind`) and a consensus layer client (`Lighthouse`) using Docker Compose. Further client combinations can be prepared using Sedge. You can also leverage alternative ways to run a node such as Ansible, Helm, or Kubernetes manifests. + + + +:::info +Currently, the [CDVN repo](https://github.com/ObolNetwork/charon-distributed-validator-node) has defaults for the Hoodi testnet and for mainnet. +::: + +Start by copying the appropriate `.env.sample.` file to `.env`, and modifying values as needed. + +```sh +# To prepare the node for the Hoodi test network +# Copy ".env.sample.hoodi", renaming it ".env" +cp .env.sample.hoodi .env + +# To prepare the node for the main Ethereum network +# Copy ".env.sample.mainnet", renaming it ".env" +cp .env.sample.mainnet .env +``` + +In the same folder where you created your ENR in Step 1, and ran the DKG in Step 3, start your node in the DV cluster with docker compose. + +```sh + +# To be run from the ./charon-distributed-validator-node folder +# Spin up a Distributed Validator Node with a Validator Client +docker compose up -d +``` + +:::danger +Do not start this node until the DKG is complete, as the charon container will interfere with the charon instance attempting to take part in the DKG ceremony. +::: + +If at any point you need to turn off your node, you can run: + +```sh +# Shut down the currently running Distributed Validator Node +docker compose down +``` + +You should use the Grafana dashboard that accompanies the quickstart repo to see whether your cluster is healthy. + +```sh +# Open Grafana dashboard +open http://localhost:3000/d/charonoverview/ +``` + +In particular you should check: + +* That your Charon client can connect to the configured beacon client. +* That your Charon client can connect to all peers directly. +* That your validator client is connected to Charon, and has the private keys it needs loaded and accessible. Most components in the dashboard have some help text there to assist you in understanding your cluster performance. You might notice that there are logs indicating that a validator cannot be found and that APIs are returning 404. This is to be expected at this point, as the validator public keys listed in the lock file have not been deposited and acknowledged on the consensus layer yet (usually it takes \~16 hours after the deposit is made). + + + +:::danger +Using a remote beacon node will impact the performance of your Distributed Validator and should be used sparingly. +::: + +If you already have a beacon node running somewhere and you want to use that instead of running an EL (`nethermind`) & CL (`lighthouse`) as part of the example repo, you can disable these images. To do so, follow these steps: + +1. Stop your docker compose + +```sh +docker compose down +``` + +2. Uncomment and set the `CHARON_BEACON_NODE_ENDPOINTS` variable in the `.env` file to your beacon node's URL + +```sh +... +# Connect to one or more external beacon nodes. Use a comma separated list excluding spaces. +CHARON_BEACON_NODE_ENDPOINTS= +... +``` + +:::info +If your existing beacon node is running in a another CDVN instance on the same Docker host, you can access it by specifying `http://host.docker.internal:5052` as the endpoint. Note: You will need to change the charon p2p port in the .env file (`CHARON_PORT_P2P_TCP=`) of the second CDVN stack to avoid port conflict. +::: + +3. Uncomment `EL=el-none` and `CL=cl-none` variables in the `.env` file and comment `EL=el-nethermind` and `CL=cl-lighthouse` variables: + +```sh +... +#EL=el-nethermind +... +EL=el-none +... +#CL=cl-lighthouse +... +CL=cl-none +... +``` + +4. Start your docker compose + +```sh +docker compose up -d +``` + + + +To prepare a Distributed Validator node using sedge, we will use the `sedge generate` command to prepare a docker-compose file of our preferred clients, `sedge import-key` to import the artifacts created during the DKG ceremony, and `sedge run` to begin running the node. + +**Sedge generate** + +With Sedge installed, and the DKG complete, it’s time to deploy a Distributed Validator. Using the `sedge generate` command and its subcommands, Sedge will create a Docker Compose file needed to run the validator node. + +1. The following command generates the artifacts required to deploy a distributed validator on the Hoodi network, using Teku as the validator client, Prysm as the consensus client, and Geth as the execution client. For additional supported client combinations, [refer to the documentation here](https://github.com/NethermindEth/sedge?tab=readme-ov-file#supported-networks-and-clients). + + ```sh + sedge generate full-node --validator=teku --consensus=prysm --execution=geth --network=hoodi --distributed + ``` + + You should be shown a long list of configuration outputs with the following endings: + + ```sh + 2024-09-20 12:56:15 -- [INFO] Generation of files successfully, happy staking! You can use now 'sedge run' to start the setup. + ``` +2. Explore the config files. + + You should now see a `sedge-data` directory created in the folder where you ran the `sedge generate` command. To view the directory contents, use the `ls` command. + + ```sh + ls sedge-data + > docker-compose.yml jwtsecret + ``` + +**Sedge Import-key** + +Use the following command to import keys from the directory where the `.charon` dir is located. + +```sh +sedge import-key --from ./ hoodi teku +``` + +**Sedge Run** + +After confirming the configurations and ensuring all files are in place, use the `sedge run` command to deploy the DV docker containers. Sedge will then begin pulling all the required Docker images. + +```sh +> sedge run +2024-09-20 13:11:49 -- [INFO] [Logger Init] Log level: info +2024-09-20 13:11:49 -- [WARN] A new Version of sedge is available. Please update to the latest Version. See https://github.com/NethermindEth/sedge/releases for more information. Latest detected tag: fatal: not a git repository (or any of the parent directories): .git +2024-09-20 13:11:50 -- [INFO] Setting up containers +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge/sedge-data/docker-compose.yml build +2024-09-20 13:11:50 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml pull +[+] Pulling 16/44 + ⠇ consensus [⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 20.8s + ⠙ b003b463d750 Downloading [===============> ] 32.9kB/103.7kB 14.2s + ⠙ fe5ca62666f0 Waiting 14.2s + ⠙ b02a7525f878 Waiting 14.2s + ⠙ fcb6f6d2c998 Waiting 14.2s + ⠙ e8c73c638ae9 Waiting 14.2s + ⠙ 1e3d9b7d1452 Waiting 14.2s + ⠙ 4aa0ea1413d3 Waiting 14.2s + ⠙ 7c881f9ab25e Waiting 14.2s + ⠙ 5627a970d25e Waiting 14.2s + ⠙ 5cf83054c259 Waiting 14.2s + ⠙ fec68abcb14d Waiting 14.2s + ⠙ 4d5ad547ce94 Waiting 14.2s + ⠙ e1ea80853e89 Waiting 14.2s + ⠙ 17b1d7e8d99a Waiting 14.2s + ⠙ 841a2fc14521 Waiting 14.2s + ⠙ 55b44d28dd62 Waiting 14.2s + ⠙ f3e3115c6547 Pulling fs layer 14.2s + ⠙ 3cec53649029 Waiting 14.2s + ⠙ 01739568079a Waiting 14.2s + ⠙ c6bd24b188db Waiting 14.2s + ⠙ fe8d2e9c9467 Waiting 14.2s + ⠙ c151008cbec0 Waiting 14.2s + ⠙ de1ef6c90686 Waiting 14.2s + ⠙ 03d09d97b125 Waiting 14.2s + ✔ execution Pulled 9.3s + ✔ a258b2a6b59a Pull complete 1.5s + ✔ a2d6cf6afda3 Pull complete 1.7s + ✔ a3dd8256fc41 Pull complete 6.9s +``` + +Once all docker images are pulled, sedge will create & start the containers to run all the required clients. See below for example output of the progress. + +```sh +✔ 8db8b5d461a7 Pull complete 24.1s + ✔ 2288b86b1d5f Pull complete 24.3s + ✔ 4becb7b9a44b Pull complete 24.3s + ✔ 4f4fb700ef54 Pull complete 24.3s + ✔ 5c35e3728c84 Pull complete 35.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml create +[+] Creating 7/7 + ✔ Network sedge-network Created 0.1s + ✔ Container sedge-dv-client Created 0.4s + ✔ Container sedge-consensus-client Created 0.4s + ✔ Container sedge-execution-client Created 0.4s + ✔ Container sedge-mev-boost Created 0.4s + ✔ Container sedge-validator-blocker Created 0.4s + ✔ Container sedge-validator-client Created 0.1s +2024-09-20 13:12:45 -- [INFO] Running command: docker compose -f /sedge-data/docker-compose.yml up -d +[+] Running 4/5 + ✔ Container sedge-consensus-client Started 1.0s + ⠧ Container sedge-validator-blocker Waiting 130.8s + ✔ Container sedge-dv-client Started 1.0s + ✔ Container sedge-execution-client Started 1.3s + ✔ Container sedge-mev-boost Started +``` + +Given time, the execution and consensus clients should complete syncing, and if a Distributed Validator has already been activated, the node should begin to validate. + +If you encounter issues with using Sedge as part of a DV cluster, consider consulting the [Sedge docs](https://docs.sedge.nethermind.io/) directly, or opening an [issue](https://github.com/NethermindEth/sedge/issues) or [pull request](https://github.com/NethermindEth/sedge/pulls) if appropriate. + + + +Use an Ansible playbook to start your node. [See the repo here](https://github.com/ObolNetwork/obol-ansible) for further instructions. + + + +Use a Helm to start your node. [See the repo here](https://github.com/ObolNetwork/helm-charts) for further instructions. + + + +Use Kubernetes manifests to start your Charon client and validator client. These manifests expect an existing Beacon Node Endpoint to connect to. [See the repo here](https://github.com/ObolNetwork/charon-k8s-distributed-validator-node) for further instructions. + + + +:::tip +In a Distributed Validator Cluster, it is important to have a low latency connection to your peers. Charon clients will use the NAT protocol to attempt to establish a direct connection to one another automatically. If this doesn't happen, you should port forward Charon's p2p port to the public internet to facilitate direct connections. The default port to expose is `:3610`. Read more about Charon's networking [here](../../learn/charon/charon-networking.md). +::: + +If you have gotten to this stage, every node is up, synced and connected, congratulations. You can now move forward to [activating your validator](../running/activate-a-dv.md) to begin staking. + +### FAQ {#faq} +
+ +What happens if I lose my ENR private key? + +If you lose your ENR private key (`.charon/charon-enr-private-key`), you won't be able to participate in the DKG ceremony or start the DV cluster successfully. It's critical to back up this file securely before proceeding with the cluster creation process. + +
+ +
+ +Can I change the cluster configuration after it's been created? + +Once a cluster configuration has been created and signed by all operators, it cannot be changed. If you need to modify the cluster settings, you'll need to create a new cluster configuration and have all operators sign the new configuration. + +
+ +
+ +What if one operator doesn't show up for the DKG ceremony? + +All operators must participate simultaneously in the DKG ceremony for it to complete successfully. If an operator is unable to participate, you'll need to wait for them or create a new cluster configuration without that operator. It's recommended to schedule the DKG ceremony at a time when all operators can participate. + +
+ +
+ +How do I know if my node is properly connected to the cluster? + +You can verify your node's connection status by checking the Grafana dashboard (if using CDVN) or monitoring the Charon logs. Your Charon client should be able to connect to all peers directly, and you should see successful handshakes in the logs. The dashboard will show connection status for each peer in the cluster. + +
+ +
+ +What should I do if the DKG ceremony fails? + +If the DKG ceremony fails, check the logs for error messages. Common issues include network connectivity problems, mismatched cluster definitions, or operators not running the command simultaneously. Ensure all operators have the correct `cluster-definition.json` file and are running the DKG command at the same time. You may need to restart the DKG process after resolving any issues. + +
+ +
+ +Can I use different client combinations for different operators in the cluster? + +Yes, each operator can use different execution and consensus clients. The Charon client handles the coordination between different client implementations, so operators can choose the clients that work best for their infrastructure while still participating in the same distributed validator cluster. + +
+ +
+ +What happens if I need to replace an operator in the cluster? + +Replacing an operator requires creating a new cluster configuration with the new operator's details and having all remaining operators plus the new operator sign the new configuration. This will require running a new DKG ceremony. For more information, see the [operator rotation guide](../../advanced-and-troubleshooting/advanced/operator-rotation.md). + +
+ +
+ +How should I set the validator count for compounding rewards? + +We recommend setting the validator count such that each validator's maxEB is capped at 1920 ETH, allowing rewards to compound for two years until it reaches 2048 ETH. [**Read more**](create-a-dv-with-a-group.mdx#step-1-get-your-enr) + +Unlike a standard bank account where interest compounds daily, validator rewards follow a step-function. Your effective balance (which earns rewards) only increases when your real balance exceeds the current effective balance by 1.25 ETH. This "hysteresis" means growth is slightly slower than pure continuous compounding, as 'dust' rewards sit idle until they accumulate enough to trigger a balance update. + +**Recommendation: The 1920 ETH Strategy** + +To maximize compounding efficiency, avoid depositing the full 2048 ETH cap immediately. Leaving \~128 ETH of "headroom" allows your validators to compound rewards autonomously for approximately 2 years (at 3% APR) before hitting the 2048 ETH effective balance cap. + +![](/img/gitbook/CompoundingRewardsCurve.png) + +
diff --git a/versioned_docs/version-v1.9/run-a-dv/start/obol-monitoring.mdx b/versioned_docs/version-v1.9/run-a-dv/start/obol-monitoring.mdx new file mode 100644 index 0000000000..bb55abba87 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/start/obol-monitoring.mdx @@ -0,0 +1,119 @@ +--- +description: "Add credentials to help the Obol Team monitor the health of your cluster" +sidebar_label: "Push Metrics and Logs to Obol" +slug: /run-a-dv/start/obol-monitoring +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Push Metrics and Logs to Obol + +:::info +This is **optional but encouraged**, and does not confer any special privileges within Obol. +::: + +## Metrics + +Metrics are statistics that are gathered on a periodic basis and used to visualise the health and performance of your Charon node and DV cluster. These metrics power your local Grafana dashboard, as well as the hosted dashboards. Submitting metrics to the Obol Core team will allow you to see advanced performance analytics on Obol's hosted platform, as well as to opt into automated alerting whenever something goes wrong with your node. + + + +This is for operators using the [example repo](https://github.com/ObolNetwork/charon-distributed-validator-node) from our [quickstart guide](quickstart_overview.md) (or [Lido equivalent](https://github.com/ObolNetwork/charon-distributed-validator-node)), and have been provided with **Monitoring Credentials** used to push Distributed Validator metrics to Obol's central Prometheus cluster to monitor, analyze, and improve their Distributed Validator Cluster's performance. (For example, this is necessary to participate in the Obol [Techne](https://squadstaking.com/techne) credential program.) + +**Update the monitoring token in the `.env` file** + +* Inside your `.env` file, uncomment the `PROM_REMOTE_WRITE_TOKEN` line by removing the `#` symbol. +* Enter your monitoring token in the format shown below: + +```shell +PROM_REMOTE_WRITE_TOKEN=your_monitoring_token +``` + +**Save the `.env` file and restart Prometheus** + +Save the `.env` file, and run the `docker compose up -d` command, and prometheus will be restarted to apply the changes. + +```shell +docker compose up -d +# Alternatively +docker compose restart prometheus +``` + + + +The last step in your DappNode setup is to add your Monitoring Credentials. This allows you to push distributed validator metrics to Obol’s central Prometheus cluster for monitoring, analysis, and performance optimization of your Distributed Validator Cluster. It also facilitates easier troubleshooting with the Obol team when needed. + +1. Get Prometheus credentials from Obol, which will look like: + + ``` + obol20tnt8UC... + ``` +2. Navigate to your Obol package in DappNode and go to the Config tab. + + ![](/img/gitbook/image-85.png) +3. At the bottom of the page, add the credential token under **Prometheus Monitoring Credentials (optional)**, then click the **Update** button. +4. Return to the **Info** tab, scroll down to the Containers section, and click the down arrow to view all container statuses. If the Prometheus container is stopped, please restart it. + + ![](/img/gitbook/image-86.png) + + + +Get a Prometheus monitoring credential from the Obol core team, it will look like: + +```log +obol20tnt8UC... +``` + +Then, either add `--set centralMonitoring.enabled=true --set-string centralMonitoring.token='YOUR_TOKEN_HERE'` to your `helm install` command, or if using a Values.yaml file, update `centralMonitoring.enabled` to `true`, and `centralMonitoring.token` to the monitoring credential you have been given, and then install/upgrade the chart. + +```yaml +# -- Central Monitoring +centralMonitoring: + # -- Specifies whether central monitoring should be enabled + enabled: true + # -- https endpoint to obol central prometheus + promEndpoint: "https://vm.monitoring.gcp.obol.tech/write" + # -- The authentication token to the central Obol prometheus instance + token: "YOUR_TOKEN_HERE" +``` + + + +## Logs + +Metrics show the performance of a cluster, but sometimes, there is reason to go into deeper detail of a clusters runtime, by reviewing its logs. Sometimes logs from the Charon client alone are sufficient, but often times (for example in the case of a missed proposal), the logs from other parts of the stack are necessary to debug a situation (e.g. a MEV-sidecar and a beacon node). + +An Obol core team member will give you a URL to send your logs to, and if feasible, sending all logs is preferable to sending only Charon logs. In custom deployments that might not be convenient or feasible, and sending only Charon logs may suffice. Follow the instructions below to configure automated log submission. + + + +If you are using one of our [Quickstart](https://github.com/ObolNetwork/charon-distributed-validator-node) [repos](https://github.com/ObolNetwork/lido-charon-distributed-validator-node), you should uncomment the `CHARON_LOKI_ADDRESSES` environment variable, and save the URL provided to you by the Obol team as the value, you should also uncomment `MONITORING=${MONITORING:-monitoring},monitoring-log-collector` to enable the [Alloy](https://grafana.com/docs/alloy/latest/) container, which collects logs from all containers and submits them to Obol. Once you've saved these changes to your `.env` file, you should run `docker compose up -d` to (re)start the containers as needed. + +```env +# Uncomment and set the log URL +CHARON_LOKI_ADDRESSES="URL here" + +# Uncomment both and set to the details of your node, otherwise the core team won't be able to isolate your logs amongst all the others +CLUSTER_NAME="The name of your cluster" +CLUSTER_PEER="The name of your peer. e.g. approachable-chair, unsightly-couch" + +# Uncomment +MONITORING=${MONITORING:-monitoring},monitoring-log-collector +``` + + + +Given a URL, you can either pass it to Charon as an additional flag to `charon run`, or by setting an environment variable on the Charon container. + +```sh +--loki-addresses="URL here" +``` + +Or: + +```env +CHARON_LOKI_ADDRESSES="URL here" +``` + + diff --git a/versioned_docs/version-v1.9/run-a-dv/start/quickstart_overview.md b/versioned_docs/version-v1.9/run-a-dv/start/quickstart_overview.md new file mode 100644 index 0000000000..e1d03b0369 --- /dev/null +++ b/versioned_docs/version-v1.9/run-a-dv/start/quickstart_overview.md @@ -0,0 +1,24 @@ +--- +sidebar_label: "Quickstart Overview" +slug: /run-a-dv/start/quickstart_overview +--- + +# Quickstart Overview + +The quickstart guides are aimed at developers and stakers looking to deploy Distributed Validators in a single or multi-operator setup. To contribute to this documentation, head over to our [Github repository](https://github.com/ObolNetwork/obol-docs) and file a pull request. + +There are two ways to set up a distributed validator and each comes with its own quickstart, within the "Getting Started" section: + +1. Run a DV cluster as a [**group**](create-a-dv-with-a-group.mdx), where several operators run the nodes that make up the cluster. In this setup, the key shares are created using a distributed key generation process, avoiding the full private keys being stored in full in any one place. This approach can also be used by single operators looking to manage all nodes of a cluster but wanting to create the key shares in a trust-minimised fashion. +2. Run a DV cluster [**alone**](create-a-dv-alone.mdx), where a single operator runs all the nodes of the DV. Depending on trust assumptions, there is not necessarily the need to create the key shares via a DKG process. Instead the key shares can be created in a centralised manner, and distributed securely to the nodes. + +## Cluster as a Service (CaaS) + +If you want to integrate DVs but are not a node operator yourself, Obol offers **Cluster as a Service (CaaS)**: distributed validators operate deep in the staking stack and are compatible with different staking strategies, and with CaaS you can select your strategy, choose your node operators, and deploy and monitor clusters with confidence. + +* [Read the Cluster as a Service offering](https://hubs.ly/Q03Y2Srl0) +* [Contact us](mailto:business@obol.tech) + +## Need assistance? + +If you have any questions about this documentation or are experiencing technical problems with any Obol-related projects, head on over to our [Discord](https://discord.gg/n6ebKsX46w) where a member of our team or the community will be happy to assist you. diff --git a/versioned_docs/version-v1.9/sdk/classes/Client.md b/versioned_docs/version-v1.9/sdk/classes/Client.md new file mode 100644 index 0000000000..913acb1f80 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/classes/Client.md @@ -0,0 +1,291 @@ +--- +sidebar_label: "Client" +slug: /sdk/classes/client +--- + +# Client + +Defined in: [index.ts:67](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L67) + +Obol sdk Client can be used for creating, managing and activating distributed validators. + +## Extends + +* `Base` + +## Constructors + +### Constructor + +> **new Client**(`config`, `signer?`, `provider?`): `Client` + +Defined in: [index.ts:113](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L113) + +#### Parameters + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------- | --------------------- | +| `config` | { `baseUrl?`: `string`; `chainId?`: `number`; } | Client configurations | +| `config.baseUrl?` | `string` | obol-api url | +| `config.chainId?` | `number` | Blockchain network ID | +| `signer?` | [`SignerType`](../type-aliases/SignerType.md) | ethersJS Signer | +| `provider?` | [`ProviderType`](../type-aliases/ProviderType.md) | - | + +#### Returns + +`Client` + +Obol-SDK Client instance + +An example of how to instantiate obol-sdk Client: [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29) + +#### Overrides + +`Base.constructor` + +## Properties + +| Property | Modifier | Type | Description | Defined in | +| ------------ | -------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `incentives` | `public` | [`Incentives`](Incentives.md) | The incentives module, responsible for managing Obol tokens distribution. | [index.ts:77](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L77) | +| `exit` | `public` | [`Exit`](Exit.md) | The exit module, responsible for managing exit validation. | [index.ts:83](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L83) | +| `splits` | `public` | [`ObolSplits`](ObolSplits.md) | The splits module, responsible for managing splits. | [index.ts:89](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L89) | +| `eoa` | `public` | [`EOA`](EOA.md) | The eoa module, responsible for managing EOA operations. | [index.ts:95](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L95) | +| `provider` | `public` | [`ProviderType`](../type-aliases/ProviderType.md) \| `null` \| `undefined` | The blockchain provider, used to interact with the network. It can be null, undefined, or a valid provider instance and defaults to the Signer provider if Signer is passed. | [index.ts:101](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L101) | + +## Methods + +### acceptObolLatestTermsAndConditions() + +> **acceptObolLatestTermsAndConditions**(): `Promise`<`string`> + +Defined in: [index.ts:143](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L143) + +Accepts Obol terms and conditions to be able to create or update data. + +#### Returns + +`Promise`<`string`> + +terms and conditions acceptance success message. + +#### Throws + +On unverified signature or wrong hash. + +An example of how to use acceptObolLatestTermsAndConditions: [acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44) + +*** + +### createObolRewardsSplit() + +> **createObolRewardsSplit**(`rewardsSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Defined in: [index.ts:198](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L198) + +Deploys OWR and Splitter Proxy. + +#### Parameters + +| Parameter | Type | Description | +| --------------------- | ------------------------------------------------------------- | --------------------------------------- | +| `rewardsSplitPayload` | [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) | Data needed to deploy owr and splitter. | + +#### Returns + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +owr address as withdrawal address and splitter as fee recipient + +An example of how to use createObolRewardsSplit: [createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141) + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +*** + +### createObolTotalSplit() + +> **createObolTotalSplit**(`totalSplitPayload`): `Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +Defined in: [index.ts:325](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L325) + +Deploys Splitter Proxy. + +#### Parameters + +| Parameter | Type | Description | +| ------------------- | ----------------------------------------------------------- | -------------------------------------------------- | +| `totalSplitPayload` | [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) | Data needed to deploy splitter if it doesnt exist. | + +#### Returns + +`Promise`<[`ClusterValidator`](../type-aliases/ClusterValidator.md)> + +splitter address as withdrawal address and splitter as fee recipient too + +An example of how to use createObolTotalSplit: [createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168) + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +*** + +### getOWRTranches() + +> **getOWRTranches**(`owrAddress`): `Promise`<[`OWRTranches`](../type-aliases/OWRTranches.md)> + +Defined in: [index.ts:430](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L430) + +Read OWR Tranches. + +#### Parameters + +| Parameter | Type | Description | +| ------------ | -------- | ------------------------------------ | +| `owrAddress` | `string` | Address of the Deployed OWR Contract | + +#### Returns + +`Promise`<[`OWRTranches`](../type-aliases/OWRTranches.md)> + +owr tranch information about principal and reward reciepient, as well as the principal amount + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed and not pushed to version control. + +*** + +### createClusterDefinition() + +> **createClusterDefinition**(`newCluster`): `Promise`<`string`> + +Defined in: [index.ts:448](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L448) + +Creates a cluster definition which contains cluster configuration. + +#### Parameters + +| Parameter | Type | Description | +| ------------ | ----------------------------------------------------- | ----------------------- | +| `newCluster` | [`ClusterPayload`](../type-aliases/ClusterPayload.md) | The new unique cluster. | + +#### Returns + +`Promise`<`string`> + +config\_hash. + +#### Throws + +On duplicate entries, missing or wrong cluster keys. + +An example of how to use createClusterDefinition: [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59) + +*** + +### acceptClusterDefinition() + +> **acceptClusterDefinition**(`operatorPayload`, `configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Defined in: [index.ts:513](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L513) + +Approves joining a cluster with specific configuration. + +#### Parameters + +| Parameter | Type | Description | +| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `operatorPayload` | [`OperatorPayload`](../type-aliases/OperatorPayload.md) | The operator data including signatures. | +| `configHash` | `string` | The config hash of the cluster which the operator confirms joining to. | + +#### Returns + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition. + +#### Throws + +On unauthorized, duplicate entries, missing keys, not found cluster or invalid data. + +An example of how to use acceptClusterDefinition: [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106) + +*** + +### getClusterDefinition() + +> **getClusterDefinition**(`configHash`): `Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +Defined in: [index.ts:570](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L570) + +#### Parameters + +| Parameter | Type | Description | +| ------------ | -------- | ---------------------------------------------------------- | +| `configHash` | `string` | The configuration hash returned in createClusterDefinition | + +#### Returns + +`Promise`<[`ClusterDefinition`](../interfaces/ClusterDefinition.md)> + +The cluster definition for config hash + +#### Throws + +On not found config hash. + +An example of how to use getClusterDefinition: [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74) + +*** + +### getClusterLock() + +> **getClusterLock**(`configHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +Defined in: [index.ts:589](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L589) + +#### Parameters + +| Parameter | Type | Description | +| ------------ | -------- | -------------------------------------------- | +| `configHash` | `string` | The configuration hash in cluster-definition | + +#### Returns + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +#### Throws + +On not found cluster definition or lock. + +An example of how to use getClusterLock: [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89) + +*** + +### getClusterLockByHash() + +> **getClusterLockByHash**(`lockHash`): `Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +Defined in: [index.ts:605](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/index.ts#L605) + +#### Parameters + +| Parameter | Type | Description | +| ---------- | -------- | -------------------------------------------- | +| `lockHash` | `string` | The configuration hash in cluster-definition | + +#### Returns + +`Promise`<[`ClusterLock`](../type-aliases/ClusterLock.md)> + +The matched cluster details (lock) from DB + +#### Throws + +On not found cluster definition or lock. diff --git a/versioned_docs/version-v1.9/sdk/classes/EOA.md b/versioned_docs/version-v1.9/sdk/classes/EOA.md new file mode 100644 index 0000000000..7f12a5ddec --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/classes/EOA.md @@ -0,0 +1,117 @@ +--- +sidebar_label: "EOA" +slug: /sdk/classes/eoa +unlisted: true +--- + +# EOA + +Defined in: [eoa/eoa.ts:26](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/eoa/eoa.ts#L26) + +**`Internal`** + +EOA can be used for managing EOA (Externally Owned Account) operations like withdrawals. + + Access it through Client.eoa. + +## Example + +```ts +const obolClient = new Client(config); +await obolClient.eoa.requestWithdrawal(EOAWithdrawalPayload); +``` + +## Methods + +### requestWithdrawal() + +> **requestWithdrawal**(`payload`): `Promise`\<\{ `txHash`: `string` \| `null`; \}\> + +Defined in: [eoa/eoa.ts:65](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/eoa/eoa.ts#L65) + +Requests withdrawal from an EOA contract. + +This method allows requesting withdrawal of validator funds. +The withdrawal request includes validator public key and corresponding withdrawal amount. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`EOAWithdrawalPayload`](../type-aliases/EOAWithdrawalPayload.md) | Data needed to request withdrawal | + +#### Returns + +`Promise`\<\{ `txHash`: `string` \| `null`; \}\> + +Transaction hash of the withdrawal request + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the signer is not provided or the request fails + +An example of how to use requestWithdrawal: +```typescript +const result = await client.eoa.requestWithdrawal({ + pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + allocation: 32, // 32 ETH + requiredFee: '1' // in wei +}); +console.log('Withdrawal requested:', result.txHash); +``` + +*** + +### deposit() + +> **deposit**(`payload`): `Promise`\<\{ `txHashes`: `string`[]; \}\> + +Defined in: [eoa/eoa.ts:132](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/eoa/eoa.ts#L132) + +Deposits to batch deposit contract. + +This method allows depositing multiple validators to the Ethereum beacon chain +using the Pier Two batch deposit contract for gas efficiency. +Each deposit includes validator public key, withdrawal credentials, signature, and amount. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`EOADepositPayload`](../type-aliases/EOADepositPayload.md) | Data needed to deposit to batch contract | + +#### Returns + +`Promise`\<\{ `txHashes`: `string`[]; \}\> + +Array of transaction hashes for all batches + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +**⚠️ Gas Limit:** Due to EVM constraints, it is recommended to deposit in batches of up to 500 at a time. + +#### Throws + +Will throw an error if the signer is not provided, contract is not configured, or the deposit fails + +An example of how to use deposit: +```typescript +const result = await client.eoa.deposit({ + deposits: [{ + pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + withdrawal_credentials: '0x1234567890123456789012345678901234567890', + deposit_data_root: '0x1234567890123456789012345678901234567890123456789012345678901234', + signature: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + amount: '32000000000000000000' // 32 ETH in wei + }] +}); +console.log('Deposits completed:', result.txHashes); +``` diff --git a/versioned_docs/version-v1.9/sdk/classes/Exit.md b/versioned_docs/version-v1.9/sdk/classes/Exit.md new file mode 100644 index 0000000000..7966ebac54 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/classes/Exit.md @@ -0,0 +1,310 @@ +--- +sidebar_label: "Exit" +slug: /sdk/classes/exit +unlisted: true +--- + +# Exit + +Defined in: [exits/exit.ts:85](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L85) + +Exit validation and verification class for Obol distributed validators. + +This class provides functionality to validate and verify voluntary exit signatures +for distributed validators in an Obol cluster. It handles both partial exit signatures +from individual operators and payload signatures that authorize exit operations. + +The class supports: +- Verification of BLS signatures for partial exit messages +- Verification of ECDSA signatures for exit payload authorization +- Validation of exit blobs against cluster configuration +- Duplicate detection and epoch validation + +## Example + +```typescript +const exit = new Exit(1, provider); // Mainnet with provider + +// Verify a partial exit signature +const isValid = await exit.verifyPartialExitSignature( + publicShareKey, + signedExitMessage, + forkVersion, + genesisValidatorsRoot +); + +// Validate exit blobs for a cluster +const validBlobs = await exit.validateExitBlobs( + clusterConfig, + exitsPayload, + beaconNodeApiUrl, + existingBlobData +); +``` + +## Constructors + +### Constructor + +> **new Exit**(`chainId`, `provider`): `Exit` + +Defined in: [exits/exit.ts:104](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L104) + +Creates a new Exit instance for validator exit operations. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `chainId` | `number` | The Ethereum chain ID (e.g., 1 for mainnet, 5 for goerli) | +| `provider` | [`ProviderType`](../type-aliases/ProviderType.md) \| `null` \| `undefined` | Optional Ethereum provider for blockchain interactions | + +#### Returns + +`Exit` + +#### Example + +```typescript +// For mainnet with a provider +const exit = new Exit(1, provider); + +// For goerli testnet without provider +const exit = new Exit(5, null); +``` + +## Methods + +### verifyPartialExitSignature() + +> **verifyPartialExitSignature**(`publicShareKey`, `signedExitMessage`, `forkVersion`, `genesisValidatorsRootString`): `Promise`\<`boolean`\> + +Defined in: [exits/exit.ts:192](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L192) + +Verifies a partial exit signature from a distributed validator operator. + +This method validates that a partial exit signature was correctly signed by the +operator's share of the distributed validator's private key. It performs BLS +signature verification using the appropriate fork version and genesis validators root. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `publicShareKey` | `string` | The operator's public share key (BLS public key, hex string with or without 0x prefix) | +| `signedExitMessage` | [`SignedExitValidationMessage`](../interfaces/SignedExitValidationMessage.md) | The signed exit message containing the exit details and signature | +| `forkVersion` | `string` | The Ethereum fork version (e.g., "0x00000000" for mainnet) | +| `genesisValidatorsRootString` | `string` | The genesis validators root for the network (hex string) | + +#### Returns + +`Promise`\<`boolean`\> + +Promise resolving to true if the signature is valid, false otherwise + +#### Throws + +When unable to determine the Capella fork version for the given network + +#### Throws + +When BLS library initialization or verification fails + +#### Example + +```typescript +const isValid = await exit.verifyPartialExitSignature( + "0x1234...abcd", // operator's public share key + { + message: { epoch: "12345", validator_index: "67890" }, + signature: "0xabcd...1234" + }, + "0x00000000", // mainnet fork version + "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95" +); +``` + +*** + +### verifyExitPayloadSignature() + +> **verifyExitPayloadSignature**(`enrString`, `exitsPayload`): `Promise`\<`boolean`\> + +Defined in: [exits/exit.ts:256](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L256) + +Verifies the exit payload signature using the operator's ENR. + +This method validates that an exit payload was signed by the correct operator +using ECDSA signature verification. The signature is verified against the +operator's public key extracted from their ENR (Ethereum Node Record). + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `enrString` | `string` | The operator's ENR string containing their identity and public key | +| `exitsPayload` | [`ExitValidationPayload`](../interfaces/ExitValidationPayload.md) | The exit validation payload containing partial exits and operator signature | + +#### Returns + +`Promise`\<`boolean`\> + +Promise resolving to true if the payload signature is valid, false otherwise + +#### Throws + +When the ENR string is invalid or cannot be decoded + +#### Throws + +When the signature format is invalid (must be 130 hex characters) + +#### Throws + +When signature verification encounters an error + +#### Example + +```typescript +const isValid = await exit.verifyExitPayloadSignature( + "enr:-LK4QFo_n0dUm4PKejSOXf8JkSWq5EINV0XhG1zY00d...", // operator ENR + { + partial_exits: [exitBlob1, exitBlob2], + share_idx: 1, + signature: "0x1234...abcd" // ECDSA signature (130 hex chars) + } +); +``` + +*** + +### validateExitBlobs() + +> **validateExitBlobs**(`clusterConfig`, `exitsPayload`, `beaconNodeApiUrl`, `existingBlobData`): `Promise`\<[`ExitValidationBlob`](../interfaces/ExitValidationBlob.md)[]\> + +Defined in: [exits/exit.ts:533](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L533) + +Validates exit blobs against cluster configuration and existing data. + +This method performs comprehensive validation of exit blobs including: +- Operator authorization and payload signature verification +- Network parameter validation (genesis root, fork version) +- Public key validation against cluster configuration +- Partial signature verification for each exit blob +- Duplicate detection and epoch progression validation +- Signature consistency checks for existing exits + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `clusterConfig` | [`ExitClusterConfig`](../interfaces/ExitClusterConfig.md) | The cluster configuration containing operators and distributed validators | +| `exitsPayload` | [`ExitValidationPayload`](../interfaces/ExitValidationPayload.md) | The exit validation payload with partial exits and operator info | +| `beaconNodeApiUrl` | `string` | The beacon node API URL for network parameter retrieval | +| `existingBlobData` | [`ExistingExitValidationBlobData`](../interfaces/ExistingExitValidationBlobData.md) \| `null` | Existing exit blob data for duplicate detection, or null if none exists | + +#### Returns + +`Promise`\<[`ExitValidationBlob`](../interfaces/ExitValidationBlob.md)[]\> + +Promise resolving to an array of validated, non-duplicate exit blobs + +#### Throws + +When share_idx is invalid or out of bounds for the cluster operators + +#### Throws + +When payload signature verification fails + +#### Throws + +When network parameters cannot be retrieved or are invalid + +#### Throws + +When a public key is not found in the cluster's distributed validators + +#### Throws + +When a partial exit signature is invalid + +#### Throws + +When exit epoch validation fails (new epoch not greater than existing) + +#### Throws + +When validator index mismatches with existing data + +#### Throws + +When signature mismatches for the same epoch and operator + +#### Example + +```typescript +const validExitBlobs = await exit.validateExitBlobs( + { + definition: { + operators: [{ enr: "enr:-LK4Q..." }], + fork_version: "0x00000000", + threshold: 1 + }, + distributed_validators: [{ + distributed_public_key: "0x1234...abcd", + public_shares: ["0x5678...efgh"] + }] + }, + { + partial_exits: [exitBlob], + share_idx: 1, + signature: "0x1234...abcd" + }, + "http://localhost:5052", + existingBlobData // or null for new exits +); +``` + +*** + +### recombineExitBlobs() + +> **recombineExitBlobs**(`exitBlob`): `Promise`\<`FullExitBlob`\> + +Defined in: [exits/exit.ts:585](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/exits/exit.ts#L585) + +Recombines exit blobs into a single exit blob. + +This method aggregates partial exit signatures from multiple operators into a single exit blob. +It ensures that the signatures are properly ordered and aggregated according to the operator indices. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `exitBlob` | [`ExistingExitValidationBlobData`](../interfaces/ExistingExitValidationBlobData.md) | The existing exit blob data containing partial exit signatures | + +#### Returns + +`Promise`\<`FullExitBlob`\> + +Promise resolving to a single exit blob with aggregated signatures + +#### Throws + +When no valid signatures are found for aggregation + +#### Throws + +When signature length is invalid + +#### Throws + +When signature parsing fails + +#### Example + +```typescript +const aggregatedExitBlob = await exit.recombineExitBlobs(existingBlobData); +``` diff --git a/versioned_docs/version-v1.9/sdk/classes/Incentives.md b/versioned_docs/version-v1.9/sdk/classes/Incentives.md new file mode 100644 index 0000000000..e783194cb9 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/classes/Incentives.md @@ -0,0 +1,114 @@ +--- +sidebar_label: "Incentives" +slug: /sdk/classes/incentives +unlisted: true +--- + +# Incentives + +Defined in: [incentives/incentives.ts:24](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L24) + +**`Internal`** + +Incentives can be used for fetching and claiming Obol incentives. + + Access it through Client.incentives. + +## Example + +```ts +const obolClient = new Client(config); +await obolClient.incentives.claimIncentives(address); +``` + +## Methods + +### claimIncentives() + +> **claimIncentives**(`address`): `Promise`\<[`ClaimIncentivesResponse`](../type-aliases/ClaimIncentivesResponse.md)\> + +Defined in: [incentives/incentives.ts:65](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L65) + +Claims Obol incentives from a Merkle Distributor contract using an address. + +This method automatically fetches incentive data and verifies whether the incentives have already been claimed. +If `txHash` is `null`, it indicates that the incentives were already claimed. + +Note: This method is not yet enabled and will throw an error if called. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `address` | `string` | The address to claim incentives for | + +#### Returns + +`Promise`\<[`ClaimIncentivesResponse`](../type-aliases/ClaimIncentivesResponse.md)\> + +The transaction hash or already claimed status + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the incentives data is not found or the claim fails + +An example of how to use claimIncentives: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L281) + +*** + +### isClaimed() + +> **isClaimed**(`contractAddress`, `index`): `Promise`\<`boolean`\> + +Defined in: [incentives/incentives.ts:124](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L124) + +Read isClaimed. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `contractAddress` | `string` | Address of the Merkle Distributor Contract | +| `index` | `number` | operator index in merkle tree | + +#### Returns + +`Promise`\<`boolean`\> + +true if incentives are already claime + +An example of how to use isClaimed: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L266) + +*** + +### getIncentivesByAddress() + +> **getIncentivesByAddress**(`address`): `Promise`\<[`ClaimableIncentives`](../type-aliases/ClaimableIncentives.md)\> + +Defined in: [incentives/incentives.ts:143](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/incentives/incentives.ts#L143) + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `address` | `string` | Operator address | + +#### Returns + +`Promise`\<[`ClaimableIncentives`](../type-aliases/ClaimableIncentives.md)\> + +The matched incentives from DB + +#### Throws + +On not found if address not found. + +An example of how to use getIncentivesByAddress: +[obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L250) diff --git a/versioned_docs/version-v1.9/sdk/classes/ObolSplits.md b/versioned_docs/version-v1.9/sdk/classes/ObolSplits.md new file mode 100644 index 0000000000..529d51d206 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/classes/ObolSplits.md @@ -0,0 +1,194 @@ +--- +sidebar_label: "ObolSplits" +slug: /sdk/classes/obolsplits +unlisted: true +--- + +# ObolSplits + +Defined in: [splits/splits.ts:42](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L42) + +**`Internal`** + +ObolSplits can be used for creating and managing Obol splits. + + Access it through Client.splits. + +## Example + +```ts +const obolClient = new Client(config); +await obolClient.splits.createValidatorManagerAndRewardsSplit(OVMRewardsSplitPayload); +``` + +## Methods + +### createValidatorManagerAndRewardsSplit() + +> **createValidatorManagerAndRewardsSplit**(`payload`): `Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +Defined in: [splits/splits.ts:76](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L76) + +Creates an Obol OVM and Pull split configuration for rewards-only scenario. + +This method deploys OVM and SplitV2 contracts for managing validator rewards only. +Principal is handled by a single address, while rewards are split among recipients. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMRewardsSplitPayload`](../type-aliases/OVMRewardsSplitPayload.md) | Data needed to deploy OVM and SplitV2 | + +#### Returns + +`Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +OVM address as withdrawal address and splitter as fee recipient + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +**📌 Note:** The Obol Validator Manager (OVM) feature is only enabled on Hoodi on launchpad. + +#### Throws + +Will throw an error if the splitter configuration is not supported or deployment fails + +An example of how to use createValidatorManagerAndRewardsSplit: +[createValidatorManagerAndRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L333) + +*** + +### createValidatorManagerAndTotalSplit() + +> **createValidatorManagerAndTotalSplit**(`payload`): `Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +Defined in: [splits/splits.ts:244](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L244) + +Creates an Obol OVM and Total split configuration for total split scenario. + +This method deploys OVM and SplitV2 contracts for managing both validator rewards and principal. +Both rewards and principal are split among recipients, with rewards including RAF recipient. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMTotalSplitPayload`](../type-aliases/OVMTotalSplitPayload.md) | Data needed to deploy OVM and SplitV2 | + +#### Returns + +`Promise`\<[`ClusterValidator`](../type-aliases/ClusterValidator.md)\> + +OVM address as withdrawal address and splitter as fee recipient + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +**📌 Note:** The Obol Validator Manager (OVM) feature is only enabled on Hoodi on launchpad. + +#### Throws + +Will throw an error if the splitter configuration is not supported or deployment fails + +An example of how to use createValidatorManagerAndTotalSplit: +[createValidatorManagerAndTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#340) + +*** + +### requestWithdrawal() + +> **requestWithdrawal**(`payload`): `Promise`\<\{ `txHash`: `string`; \}\> + +Defined in: [splits/splits.ts:442](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L442) + +Requests withdrawal from an OVM contract. + +This method allows requesting withdrawal of validator funds from an OVM contract. +The withdrawal request includes OVM address, validator public keys and corresponding withdrawal amounts. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMRequestWithdrawalPayload`](../type-aliases/OVMRequestWithdrawalPayload.md) | Data needed to request withdrawal | + +#### Returns + +`Promise`\<\{ `txHash`: `string`; \}\> + +Transaction hash of the withdrawal request + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the signer is not provided, OVM address is invalid, or the request fails + +An example of how to use requestWithdrawal: +```typescript +const result = await client.splits.requestWithdrawal({ + ovmAddress: '0x1234567890123456789012345678901234567890', + pubKeys: ['0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456'], + amounts: ['32000000000'], // 32 ETH in gwei + withdrawalFees: '1000000000000000' // Total fees in wei +}); +console.log('Withdrawal requested:', result.txHash); +``` + +*** + +### deposit() + +> **deposit**(`payload`): `Promise`\<\{ `txHashes`: `string`[]; \}\> + +Defined in: [splits/splits.ts:492](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/splits/splits.ts#L492) + +Deposits to OVM contract by sending individual transactions for each deposit. + +This method allows depositing to an OVM contract. Each deposit is sent as a separate transaction +Each deposit includes validator public key, withdrawal credentials, signature, deposit data root, and amount. + +#### Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `payload` | [`OVMDepositPayload`](../type-aliases/OVMDepositPayload.md) | Data needed to deposit to OVM | + +#### Returns + +`Promise`\<\{ `txHashes`: `string`[]; \}\> + +Array of transaction hashes, one for each deposit + +#### Remarks + +**⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed +and not pushed to version control. + +#### Throws + +Will throw an error if the signer is not provided, OVM address is invalid, or the deposit fails + +An example of how to use deposit: +```typescript +const result = await client.splits.deposit({ + ovmAddress: '0x1234567890123456789012345678901234567890', + deposits: [{ + pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + withdrawal_credentials: '0x1234567890123456789012345678901234567890', + signature: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456', + deposit_data_root: '0x1234567890123456789012345678901234567890123456789012345678901234', + amount: '32000000000000000000' // 32 ETH in wei + }] +}); +console.log('Deposits completed:', result.txHashes); +``` diff --git a/versioned_docs/version-v1.9/sdk/classes/README.md b/versioned_docs/version-v1.9/sdk/classes/README.md new file mode 100644 index 0000000000..2c00796913 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/classes/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Classes" +slug: /sdk/classes +--- + +# Classes + diff --git a/versioned_docs/version-v1.9/sdk/enumerations/FORK_MAPPING.md b/versioned_docs/version-v1.9/sdk/enumerations/FORK_MAPPING.md new file mode 100644 index 0000000000..df8819a9c5 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/enumerations/FORK_MAPPING.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "FORK_MAPPING" +slug: /sdk/enumerations/fork_mapping +--- + +# FORK\_MAPPING + +Defined in: [types.ts:13](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L13) + +Permitted ChainID's + +## Enumeration Members + +| Enumeration Member | Value | Description | Defined in | +| ------------------ | ---------- | -------------- | --------------------------------------------------------------------------------------------------------------------- | +| `0x00000000` | `1` | Mainnet. | [types.ts:15](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L15) | +| `0x00001020` | `5` | Goerli/Prater. | [types.ts:18](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L18) | +| `0x00000064` | `100` | Gnosis Chain. | [types.ts:21](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L21) | +| `0x01017000` | `17000` | Holesky. | [types.ts:24](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L24) | +| `0x90000069` | `11155111` | Sepolia. | [types.ts:27](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L27) | +| `0x10000910` | `560048` | Hoodi Chain. | [types.ts:30](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L30) | diff --git a/versioned_docs/version-v1.9/sdk/enumerations/README.md b/versioned_docs/version-v1.9/sdk/enumerations/README.md new file mode 100644 index 0000000000..c5e9c93aa7 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/enumerations/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Enumerations" +slug: /sdk/enumerations +--- + +# Enumerations + diff --git a/versioned_docs/version-v1.9/sdk/functions/README.md b/versioned_docs/version-v1.9/sdk/functions/README.md new file mode 100644 index 0000000000..082855458f --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/functions/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Functions" +slug: /sdk/functions +--- + +# Functions + diff --git a/versioned_docs/version-v1.9/sdk/functions/clusterConfigOrDefinitionHash.md b/versioned_docs/version-v1.9/sdk/functions/clusterConfigOrDefinitionHash.md new file mode 100644 index 0000000000..a45a6f0718 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/functions/clusterConfigOrDefinitionHash.md @@ -0,0 +1,24 @@ +--- +sidebar_label: "clusterConfigOrDefinitionHash()" +slug: /sdk/functions/clusterconfigordefinitionhash +unlisted: true +--- + +# clusterConfigOrDefinitionHash() + +> **clusterConfigOrDefinitionHash**(`cluster`, `configOnly`): `string` + +Defined in: [verification/common.ts:64](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L64) + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `cluster` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster configuration or the cluster definition | +| `configOnly` | `boolean` | a boolean to indicate config hash or definition hash | + +## Returns + +`string` + +The config hash or the definition hash in of the corresponding cluster diff --git a/versioned_docs/version-v1.9/sdk/functions/clusterLockHash.md b/versioned_docs/version-v1.9/sdk/functions/clusterLockHash.md new file mode 100644 index 0000000000..bd6893e8fd --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/functions/clusterLockHash.md @@ -0,0 +1,25 @@ +--- +sidebar_label: "clusterLockHash()" +slug: /sdk/functions/clusterlockhash +unlisted: true +--- + +# clusterLockHash() + +> **clusterLockHash**(`clusterLock`): `string` + +Defined in: [verification/common.ts:116](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L116) + +Returns the SSZ cluster lock hash of the given cluster lock object + +## Parameters + +| Parameter | Type | +| ------ | ------ | +| `clusterLock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | + +## Returns + +`string` + +The cluster lock hash in of the corresponding cluster lock diff --git a/versioned_docs/version-v1.9/sdk/functions/validateClusterLock.md b/versioned_docs/version-v1.9/sdk/functions/validateClusterLock.md new file mode 100644 index 0000000000..455ac41b70 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/functions/validateClusterLock.md @@ -0,0 +1,31 @@ +--- +sidebar_label: "validateClusterLock" +slug: /sdk/functions/validateclusterlock +--- + +# validateClusterLock + +> **validateClusterLock**(`lock`, `safeRpcUrl?`): `Promise`<`boolean`> + +Defined in: [services.ts:14](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/services.ts#L14) + +Verifies Cluster Lock's validity. + +## Parameters + +| Parameter | Type | Description | +| ------------- | ----------------------------------------------- | ------------------------------------------------ | +| `lock` | [`ClusterLock`](../type-aliases/ClusterLock.md) | cluster lock | +| `safeRpcUrl?` | `string` | optional safeRpcUrl for safe wallet verification | + +## Returns + +`Promise`<`boolean`> + +boolean result to indicate if lock is valid + +## Throws + +on missing keys or values. + +An example of how to use validateClusterLock: [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127) diff --git a/versioned_docs/version-v1.9/sdk/functions/verifyDepositData.md b/versioned_docs/version-v1.9/sdk/functions/verifyDepositData.md new file mode 100644 index 0000000000..bd9fa10451 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/functions/verifyDepositData.md @@ -0,0 +1,34 @@ +--- +sidebar_label: "verifyDepositData()" +slug: /sdk/functions/verifydepositdata +unlisted: true +--- + +# verifyDepositData() + +> **verifyDepositData**(`distributedPublicKey`, `depositData`, `withdrawalAddress`, `forkVersion`, `compounding?`): `object` + +Defined in: [verification/common.ts:362](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L362) + +Verify deposit data withdrawal credintials and signature + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `distributedPublicKey` | `string` | - | +| `depositData` | `Partial`\<[`DepositData`](../type-aliases/DepositData.md)\> | - | +| `withdrawalAddress` | `string` | withdrawal address in definition file. | +| `forkVersion` | `string` | fork version in definition file. | +| `compounding?` | `boolean` | - | + +## Returns + +`object` + +- return if deposit data is valid. + +| Name | Type | Defined in | +| ------ | ------ | ------ | +| `isValidDepositData` | `boolean` | [verification/common.ts:368](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L368) | +| `depositDataMsg` | `Uint8Array` | [verification/common.ts:368](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/verification/common.ts#L368) | diff --git a/versioned_docs/version-v1.9/sdk/index.md b/versioned_docs/version-v1.9/sdk/index.md new file mode 100644 index 0000000000..7b898c684f --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/index.md @@ -0,0 +1,168 @@ +--- +sidebar_label: "Intro" +slug: /sdk/index +--- + +# Intro + +**SDK Version:** v2.11.8 + +![Obol Logo](https://obol.org/obolnetwork.png) + +## Obol SDK + +This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](../api/what-is-this-api.md). + +## Getting Started + +Checkout our [docs](../advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk.mdx), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://obolnetwork.github.io/obol-sdk). Further guides and walkthroughs coming soon. + +### Terms and Conditions + +## Terms and Conditions + +To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions. + +## ⚠️ Important Security Notice: + +If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that: + +* The private key is securely stored (e.g., in an `.env` file). +* Never commit or push your `.env` file containing the private key to version control. + +## ⚡️ Integration with Safe Wallet + +When integrating the Obol SDK with a **Safe Wallet**, you can either pass an RPC URL OR provide the `RPC_MAINNET` or `RPC_HOLESKY` or `RPC_GNOSIS` or `RPC_SEPOLIA` or `RPC_HOODI` environment variable, pointing to the correct network's RPC URL. This is required to interact with Safe kit. + +## Contributing + +Please review the following guidelines: + +* [How to Report Bugs](index.md#how-to-report-bugs) +* [How to Propose Changes](index.md#how-to-propose-changes) +* [Code Review Process](index.md#code-review-process) + +### How to Report Bugs + +If you encounter a bug or unexpected behavior, please follow these steps to report it: + +1. Go to the "Issues" tab of this repository. +2. Click on the "Get started" button in the Bug report section. +3. Provide a clear title and description of the issue following the format provided. + +### How to Propose Changes + +If you'd like to propose improvements or new features, please follow these steps: + +1. Fork this repository. +2. Create a new branch for your changes. +3. Make your changes and commit them with clear messages. +4. Open a pull request with a detailed description of the changes. + +### Code Review Process + +All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process. + +Thank you for contributing to Obol-SDK! + +## Next.js / SSR Configuration + +If using this SDK in **Next.js** or other SSR frameworks, add this minimal config to your `next.config.js`: + +```javascript +webpack: (config, { isServer, webpack }) => { + if (!isServer) { + config.plugins.push( + new webpack.DefinePlugin({ + 'process.stdout.isTTY': 'false', + 'process.stderr.isTTY': 'false', + }) + ); + } else { + // Server: Externalize native dependencies + config.externals = config.externals || []; + config.externals.push({ + '@chainsafe/bls': 'commonjs @chainsafe/bls', + '@chainsafe/blst': 'commonjs @chainsafe/blst', + 'bcrypto': 'commonjs bcrypto', + }); + } + + // Ignore .node files + config.plugins.push( + new webpack.IgnorePlugin({ resourceRegExp: /\.node$/ }) + ); + + return config; +} +``` + +## Enumerations + +* [FORK\_MAPPING](enumerations/FORK_MAPPING.md) + +## Classes + +* [EOA](classes/EOA.md) +* [Exit](classes/Exit.md) +* [Incentives](classes/Incentives.md) +* [Client](classes/Client.md) +* [ObolSplits](classes/ObolSplits.md) + +## Interfaces + +* [ClusterDefinition](interfaces/ClusterDefinition.md) +* [RewardsSplitPayload](interfaces/RewardsSplitPayload.md) +* [ExitOperator](interfaces/ExitOperator.md) +* [ExitClusterDefinition](interfaces/ExitClusterDefinition.md) +* [ExitDistributedValidator](interfaces/ExitDistributedValidator.md) +* [ExitClusterConfig](interfaces/ExitClusterConfig.md) +* [ExitValidationMessage](interfaces/ExitValidationMessage.md) +* [SignedExitValidationMessage](interfaces/SignedExitValidationMessage.md) +* [ExitValidationBlob](interfaces/ExitValidationBlob.md) +* [ExitValidationPayload](interfaces/ExitValidationPayload.md) +* [ExistingExitValidationBlobData](interfaces/ExistingExitValidationBlobData.md) + +## Type Aliases + +* [ClusterOperator](type-aliases/ClusterOperator.md) +* [OperatorPayload](type-aliases/OperatorPayload.md) +* [ClusterCreator](type-aliases/ClusterCreator.md) +* [ClusterValidator](type-aliases/ClusterValidator.md) +* [ClusterPayload](type-aliases/ClusterPayload.md) +* [SplitRecipient](type-aliases/SplitRecipient.md) +* [TotalSplitPayload](type-aliases/TotalSplitPayload.md) +* [OVMBaseSplitPayload](type-aliases/OVMBaseSplitPayload.md) +* [OVMRewardsSplitPayload](type-aliases/OVMRewardsSplitPayload.md) +* [OVMTotalSplitPayload](type-aliases/OVMTotalSplitPayload.md) +* [OVMSplitPayload](type-aliases/OVMSplitPayload.md) +* [SplitV2Recipient](type-aliases/SplitV2Recipient.md) +* [OWRTranches](type-aliases/OWRTranches.md) +* [BuilderRegistrationMessage](type-aliases/BuilderRegistrationMessage.md) +* [BuilderRegistration](type-aliases/BuilderRegistration.md) +* [DepositData](type-aliases/DepositData.md) +* [DistributedValidator](type-aliases/DistributedValidator.md) +* [ClusterLock](type-aliases/ClusterLock.md) +* [ClaimableIncentives](type-aliases/ClaimableIncentives.md) +* [ETH\_ADDRESS](type-aliases/ETH_ADDRESS.md) +* [ProviderType](type-aliases/ProviderType.md) +* [SafeRpcUrl](type-aliases/SafeRpcUrl.md) +* [SignerType](type-aliases/SignerType.md) +* [ClaimIncentivesResponse](type-aliases/ClaimIncentivesResponse.md) +* [HttpRequestFunc](type-aliases/HttpRequestFunc.md) +* [OVMArgs](type-aliases/OVMArgs.md) +* [OVMRequestWithdrawalPayload](type-aliases/OVMRequestWithdrawalPayload.md) +* [EOAWithdrawalPayload](type-aliases/EOAWithdrawalPayload.md) +* [OVMDepositPayload](type-aliases/OVMDepositPayload.md) +* [EOADepositPayload](type-aliases/EOADepositPayload.md) + +## Variables + +* [CAPELLA\_FORK\_MAPPING](variables/CAPELLA_FORK_MAPPING.md) + +## Functions + +* [validateClusterLock](functions/validateClusterLock.md) +* [clusterConfigOrDefinitionHash](functions/clusterConfigOrDefinitionHash.md) +* [clusterLockHash](functions/clusterLockHash.md) +* [verifyDepositData](functions/verifyDepositData.md) diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ClusterDefinition.md b/versioned_docs/version-v1.9/sdk/interfaces/ClusterDefinition.md new file mode 100644 index 0000000000..82bf7ed6f1 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ClusterDefinition.md @@ -0,0 +1,36 @@ +--- +sidebar_label: "ClusterDefinition" +slug: /sdk/interfaces/clusterdefinition +--- + +# ClusterDefinition + +Defined in: [types.ts:121](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L121) + +Cluster definition data needed for dkg + +## Extends + +* [`ClusterPayload`](../type-aliases/ClusterPayload.md) + +## Properties + +| Property | Type | Description | Overrides | Inherited from | Defined in | +| --------------------- | ------------------------------------------------------------ | -------------------------------------------------------- | ----------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | The cluster name. | - | `ClusterPayload.name` | [types.ts:97](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L97) | +| `operators` | [`ClusterOperator`](../type-aliases/ClusterOperator.md)\[] | The cluster nodes operators addresses. | - | `ClusterPayload.operators` | [types.ts:100](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L100) | +| `validators` | [`ClusterValidator`](../type-aliases/ClusterValidator.md)\[] | The cluster validators information. | - | `ClusterPayload.validators` | [types.ts:103](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L103) | +| `deposit_amounts?` | `string`\[] \| `null` | The cluster partial deposits in gwei or 32000000000. | - | `ClusterPayload.deposit_amounts` | [types.ts:106](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L106) | +| `creator` | [`ClusterCreator`](../type-aliases/ClusterCreator.md) | The creator of the cluster. | - | - | [types.ts:123](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L123) | +| `version` | `string` | The cluster configuration version. | - | - | [types.ts:126](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L126) | +| `dkg_algorithm` | `string` | The cluster dkg algorithm. | - | - | [types.ts:129](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L129) | +| `fork_version` | `string` | The cluster fork version. | - | - | [types.ts:132](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L132) | +| `uuid` | `string` | The cluster uuid. | - | - | [types.ts:135](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L135) | +| `timestamp` | `string` | The cluster creation timestamp. | - | - | [types.ts:138](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L138) | +| `config_hash` | `string` | The cluster configuration hash. | - | - | [types.ts:141](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L141) | +| `threshold` | `number` | The distributed validator threshold. | - | - | [types.ts:144](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L144) | +| `num_validators` | `number` | The number of distributed validators in the cluster. | - | - | [types.ts:147](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L147) | +| `definition_hash?` | `string` | The hash of the cluster definition. | - | - | [types.ts:150](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L150) | +| `consensus_protocol?` | `string` | The consensus protocol e.g qbft. | `ClusterPayload.consensus_protocol` | - | [types.ts:153](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L153) | +| `target_gas_limit?` | `number` | The target gas limit where default is 36M. | `ClusterPayload.target_gas_limit` | - | [types.ts:156](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L156) | +| `compounding?` | `boolean` | A withdrawal mechanism with 0x02 withdrawal credentials. | `ClusterPayload.compounding` | - | [types.ts:159](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L159) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExistingExitValidationBlobData.md b/versioned_docs/version-v1.9/sdk/interfaces/ExistingExitValidationBlobData.md new file mode 100644 index 0000000000..f571985d1a --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExistingExitValidationBlobData.md @@ -0,0 +1,20 @@ +--- +sidebar_label: "ExistingExitValidationBlobData" +slug: /sdk/interfaces/existingexitvalidationblobdata +unlisted: true +--- + +# ExistingExitValidationBlobData + +Defined in: [types.ts:501](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L501) + +Represents the data structure for an already existing exit blob for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `public_key` | `string` | The BLS public key of the validator in hex format | [types.ts:505](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L505) | +| `epoch` | `string` | The epoch number when the exit is scheduled to occur | [types.ts:509](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L509) | +| `validator_index` | `string` | The unique index of the validator in the beacon chain | [types.ts:513](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L513) | +| `shares_exit_data` | `Record`\<`string`, \{ `partial_exit_signature`: `string`; \}\>[] | Array of distributed validator shares exit data, where each share contains the partial exit signature from each operator in the cluster | [types.ts:518](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L518) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitClusterConfig.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitClusterConfig.md new file mode 100644 index 0000000000..3a86d36eca --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitClusterConfig.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitClusterConfig" +slug: /sdk/interfaces/exitclusterconfig +unlisted: true +--- + +# ExitClusterConfig + +Defined in: [types.ts:443](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L443) + +Combined cluster information needed for exit validation in the SDK. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `definition` | [`ExitClusterDefinition`](ExitClusterDefinition.md) | The cluster definition with operators, fork version and threshold. | [types.ts:445](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L445) | +| `distributed_validators` | [`ExitDistributedValidator`](ExitDistributedValidator.md)[] | The cluster distributed validators. | [types.ts:448](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L448) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitClusterDefinition.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitClusterDefinition.md new file mode 100644 index 0000000000..79859a1a8c --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitClusterDefinition.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ExitClusterDefinition" +slug: /sdk/interfaces/exitclusterdefinition +unlisted: true +--- + +# ExitClusterDefinition + +Defined in: [types.ts:418](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L418) + +Represents the core definition of a cluster relevant for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `operators` | [`ExitOperator`](ExitOperator.md)[] | The cluster nodes operators with their ENRs. | [types.ts:420](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L420) | +| `fork_version` | `string` | The cluster fork version. | [types.ts:423](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L423) | +| `threshold` | `number` | The distributed validator threshold. | [types.ts:426](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L426) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitDistributedValidator.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitDistributedValidator.md new file mode 100644 index 0000000000..f5b618ab29 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitDistributedValidator.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitDistributedValidator" +slug: /sdk/interfaces/exitdistributedvalidator +unlisted: true +--- + +# ExitDistributedValidator + +Defined in: [types.ts:432](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L432) + +Represents a distributed validator's information relevant for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `distributed_public_key` | `string` | The public key of the distributed validator. | [types.ts:434](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L434) | +| `public_shares` | `string`[] | The public key shares of the distributed validator. | [types.ts:437](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L437) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitOperator.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitOperator.md new file mode 100644 index 0000000000..33308efb1b --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitOperator.md @@ -0,0 +1,17 @@ +--- +sidebar_label: "ExitOperator" +slug: /sdk/interfaces/exitoperator +unlisted: true +--- + +# ExitOperator + +Defined in: [types.ts:410](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L410) + +Represents the structure of an Ethereum operator for exit validation, primarily their ENR. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `enr` | `string` | The operator's Ethereum Node Record (ENR). | [types.ts:412](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L412) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationBlob.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationBlob.md new file mode 100644 index 0000000000..13029de46b --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationBlob.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitValidationBlob" +slug: /sdk/interfaces/exitvalidationblob +unlisted: true +--- + +# ExitValidationBlob + +Defined in: [types.ts:476](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L476) + +Represents a single partial exit blob for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `public_key` | `string` | The public key of the validator to exit. | [types.ts:478](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L478) | +| `signed_exit_message` | [`SignedExitValidationMessage`](SignedExitValidationMessage.md) | The signed exit message for the validator. | [types.ts:481](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L481) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationMessage.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationMessage.md new file mode 100644 index 0000000000..df7402241f --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationMessage.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "ExitValidationMessage" +slug: /sdk/interfaces/exitvalidationmessage +unlisted: true +--- + +# ExitValidationMessage + +Defined in: [types.ts:454](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L454) + +Represents the message part of a signed exit for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `epoch` | `string` | The epoch at which the validator wishes to exit. | [types.ts:456](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L456) | +| `validator_index` | `string` | The index of the validator in the beacon chain. | [types.ts:459](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L459) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationPayload.md b/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationPayload.md new file mode 100644 index 0000000000..91ee5bc77d --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/ExitValidationPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ExitValidationPayload" +slug: /sdk/interfaces/exitvalidationpayload +unlisted: true +--- + +# ExitValidationPayload + +Defined in: [types.ts:487](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L487) + +Represents the overall exit payload structure for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `partial_exits` | [`ExitValidationBlob`](ExitValidationBlob.md)[] | Array of partial exits for validators. | [types.ts:489](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L489) | +| `share_idx` | `number` | Operator's share index (1-based). | [types.ts:492](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L492) | +| `signature` | `string` | Signature of the ExitValidationPayload by the operator. | [types.ts:495](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L495) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/README.md b/versioned_docs/version-v1.9/sdk/interfaces/README.md new file mode 100644 index 0000000000..c39173096c --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Interfaces" +slug: /sdk/interfaces +--- + +# Interfaces + diff --git a/versioned_docs/version-v1.9/sdk/interfaces/RewardsSplitPayload.md b/versioned_docs/version-v1.9/sdk/interfaces/RewardsSplitPayload.md new file mode 100644 index 0000000000..c568152261 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/RewardsSplitPayload.md @@ -0,0 +1,26 @@ +--- +sidebar_label: "RewardsSplitPayload" +slug: /sdk/interfaces/rewardssplitpayload +--- + +# RewardsSplitPayload + +Defined in: [types.ts:193](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L193) + +OWR and Split Proxy Params + +## Extends + +* [`TotalSplitPayload`](../type-aliases/TotalSplitPayload.md) + +## Properties + +| Property | Type | Description | Inherited from | Defined in | +| -------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `splitRecipients` | [`SplitRecipient`](../type-aliases/SplitRecipient.md)\[] | The split recipients addresses and splits. | `TotalSplitPayload.splitRecipients` | [types.ts:178](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L178) | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | `TotalSplitPayload.ObolRAFSplit` | [types.ts:181](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L181) | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | `TotalSplitPayload.distributorFee` | [types.ts:184](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L184) | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | `TotalSplitPayload.controllerAddress` | [types.ts:187](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L187) | +| `principalRecipient` | `string` | Address that will reclaim validator principal after exit. | - | [types.ts:195](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L195) | +| `etherAmount` | `number` | Amount needed to deploy all validators expected for the OWR/Splitter configuration. | - | [types.ts:198](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L198) | +| `recoveryAddress?` | `string` | Address that can control where the owr erc-20 tokens can be pushed, if set to zero it goes to splitter or principal address. | - | [types.ts:201](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L201) | diff --git a/versioned_docs/version-v1.9/sdk/interfaces/SignedExitValidationMessage.md b/versioned_docs/version-v1.9/sdk/interfaces/SignedExitValidationMessage.md new file mode 100644 index 0000000000..8896c283a1 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/interfaces/SignedExitValidationMessage.md @@ -0,0 +1,18 @@ +--- +sidebar_label: "SignedExitValidationMessage" +slug: /sdk/interfaces/signedexitvalidationmessage +unlisted: true +--- + +# SignedExitValidationMessage + +Defined in: [types.ts:465](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L465) + +Represents a signed exit message for exit validation. + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `message` | [`ExitValidationMessage`](ExitValidationMessage.md) | The exit message containing epoch and validator index. | [types.ts:467](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L467) | +| `signature` | `string` | BLS signature of the exit message. | [types.ts:470](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L470) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/BuilderRegistration.md b/versioned_docs/version-v1.9/sdk/type-aliases/BuilderRegistration.md new file mode 100644 index 0000000000..b339f1c118 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/BuilderRegistration.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "BuilderRegistration" +slug: /sdk/type-aliases/builderregistration +--- + +# BuilderRegistration + +> **BuilderRegistration** = `object` + +Defined in: [types.ts:290](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L290) + +Pre-generated Signed Validator Builder Registration + +## Properties + +| Property | Type | Description | Defined in | +| ----------- | ------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `message` | [`BuilderRegistrationMessage`](BuilderRegistrationMessage.md) | Builder registration message. | [types.ts:292](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L292) | +| `signature` | `string` | BLS signature of the builder registration message. | [types.ts:295](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L295) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/BuilderRegistrationMessage.md b/versioned_docs/version-v1.9/sdk/type-aliases/BuilderRegistrationMessage.md new file mode 100644 index 0000000000..20e3cdc17b --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/BuilderRegistrationMessage.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "BuilderRegistrationMessage" +slug: /sdk/type-aliases/builderregistrationmessage +--- + +# BuilderRegistrationMessage + +> **BuilderRegistrationMessage** = `object` + +Defined in: [types.ts:273](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L273) + +Unsigned DV Builder Registration Message + +## Properties + +| Property | Type | Description | Defined in | +| --------------- | -------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `fee_recipient` | `string` | The DV fee recipient. | [types.ts:275](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L275) | +| `gas_limit` | `number` | Default is 30000000. | [types.ts:278](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L278) | +| `timestamp` | `number` | Timestamp when generating cluster lock file. | [types.ts:281](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L281) | +| `pubkey` | `string` | The public key of the DV. | [types.ts:284](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L284) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClaimIncentivesResponse.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClaimIncentivesResponse.md new file mode 100644 index 0000000000..4167ef05d5 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClaimIncentivesResponse.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "ClaimIncentivesResponse" +slug: /sdk/type-aliases/claimincentivesresponse +unlisted: true +--- + +# ClaimIncentivesResponse + +> **ClaimIncentivesResponse** = `object` + +Defined in: [types.ts:405](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L405) + +claimIncentives Response diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClaimableIncentives.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClaimableIncentives.md new file mode 100644 index 0000000000..0152874a04 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClaimableIncentives.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClaimableIncentives" +slug: /sdk/type-aliases/claimableincentives +unlisted: true +--- + +# ClaimableIncentives + +> **ClaimableIncentives** = `object` + +Defined in: [types.ts:361](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L361) + +Claimable Obol Incentives + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `operator_address` | `string` | Operator Address. | [types.ts:363](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L363) | +| `amount` | `string` | The amount the recipient is entitled to. | [types.ts:366](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L366) | +| `index` | `number` | The recipient's index in the Merkle tree. | [types.ts:369](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L369) | +| `merkle_proof` | `string`[] | The Merkle proof (an array of hashes) generated for the recipient. | [types.ts:372](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L372) | +| `contract_address` | `string` | The MerkleDistributor contract address. | [types.ts:375](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L375) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClusterCreator.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterCreator.md new file mode 100644 index 0000000000..5d34fc7eb7 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterCreator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterCreator" +slug: /sdk/type-aliases/clustercreator +--- + +# ClusterCreator + +> **ClusterCreator** = `object` + +Defined in: [types.ts:74](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L74) + +Cluster creator data + +## Properties + +| Property | Type | Description | Defined in | +| ------------------- | -------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | +| `address` | `string` | The creator address. | [types.ts:76](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L76) | +| `config_signature?` | `string` | The cluster configuration signature. | [types.ts:78](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L78) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClusterLock.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterLock.md new file mode 100644 index 0000000000..18f451fba8 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterLock.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "ClusterLock" +slug: /sdk/type-aliases/clusterlock +--- + +# ClusterLock + +> **ClusterLock** = `object` + +Defined in: [types.ts:341](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L341) + +Cluster Details after DKG is complete + +## Properties + +| Property | Type | Description | Defined in | +| ------------------------ | --------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `cluster_definition` | [`ClusterDefinition`](../interfaces/ClusterDefinition.md) | The cluster definition. | [types.ts:343](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L343) | +| `distributed_validators` | [`DistributedValidator`](DistributedValidator.md)\[] | The cluster distributed validators. | [types.ts:346](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L346) | +| `signature_aggregate` | `string` | The cluster bls signature aggregate. | [types.ts:349](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L349) | +| `lock_hash` | `string` | The hash of the cluster lock. | [types.ts:352](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L352) | +| `node_signatures?` | `string`\[] | Node Signature for the lock hash by the node secp256k1 key. | [types.ts:355](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L355) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClusterOperator.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterOperator.md new file mode 100644 index 0000000000..bf30d530ae --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterOperator.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "ClusterOperator" +slug: /sdk/type-aliases/clusteroperator +--- + +# ClusterOperator + +> **ClusterOperator** = `object` + +Defined in: [types.ts:45](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L45) + +Node operator data + +## Properties + +| Property | Type | Description | Defined in | +| ------------------- | -------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| `address` | `string` | The operator address. | [types.ts:47](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L47) | +| `enr?` | `string` | The operator ethereum node record. | [types.ts:50](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L50) | +| `fork_version?` | `string` | The cluster fork\_version. | [types.ts:53](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L53) | +| `version?` | `string` | The cluster version. | [types.ts:56](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L56) | +| `enr_signature?` | `string` | The operator enr signature. | [types.ts:59](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L59) | +| `config_signature?` | `string` | The operator configuration signature. | [types.ts:62](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L62) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClusterPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterPayload.md new file mode 100644 index 0000000000..18eca9bddc --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterPayload.md @@ -0,0 +1,28 @@ +--- +sidebar_label: "ClusterPayload" +slug: /sdk/type-aliases/clusterpayload +--- + +# ClusterPayload + +> **ClusterPayload** = `object` + +Defined in: [types.ts:95](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L95) + +Cluster configuration + +## Extended by + +* [`ClusterDefinition`](../interfaces/ClusterDefinition.md) + +## Properties + +| Property | Type | Description | Defined in | +| --------------------- | -------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | The cluster name. | [types.ts:97](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L97) | +| `operators` | [`ClusterOperator`](ClusterOperator.md)\[] | The cluster nodes operators addresses. | [types.ts:100](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L100) | +| `validators` | [`ClusterValidator`](ClusterValidator.md)\[] | The cluster validators information. | [types.ts:103](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L103) | +| `deposit_amounts?` | `string`\[] \| `null` | The cluster partial deposits in gwei or 32000000000. | [types.ts:106](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L106) | +| `compounding?` | `boolean` | A withdrawal mechanism with 0x02 withdrawal credentials. | [types.ts:109](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L109) | +| `target_gas_limit?` | `number` | The target gas limit where default is 36M. | [types.ts:112](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L112) | +| `consensus_protocol?` | `string` | The consensus protocol e.g qbft. | [types.ts:115](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L115) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ClusterValidator.md b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterValidator.md new file mode 100644 index 0000000000..4c5d05b06d --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ClusterValidator.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "ClusterValidator" +slug: /sdk/type-aliases/clustervalidator +--- + +# ClusterValidator + +> **ClusterValidator** = `object` + +Defined in: [types.ts:84](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L84) + +Validator withdrawal configuration + +## Properties + +| Property | Type | Description | Defined in | +| ----------------------- | -------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | +| `fee_recipient_address` | `string` | Address to receive MEV rewards (if enabled), block proposal and priority fees. | [types.ts:86](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L86) | +| `withdrawal_address` | `string` | Address to receive skimming rewards and validator principal at exit. | [types.ts:89](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L89) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/DepositData.md b/versioned_docs/version-v1.9/sdk/type-aliases/DepositData.md new file mode 100644 index 0000000000..d36f32fad8 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/DepositData.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DepositData" +slug: /sdk/type-aliases/depositdata +--- + +# DepositData + +> **DepositData** = `object` + +Defined in: [types.ts:301](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L301) + +Required deposit data for validator activation + +## Properties + +| Property | Type | Description | Defined in | +| ------------------------ | -------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `pubkey` | `string` | The public key of the distributed validator. | [types.ts:303](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L303) | +| `withdrawal_credentials` | `string` | The 0x01 withdrawal address of the DV. | [types.ts:306](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L306) | +| `amount` | `string` | 32 ethers. | [types.ts:309](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L309) | +| `deposit_data_root` | `string` | A checksum for DepositData fields . | [types.ts:312](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L312) | +| `signature` | `string` | BLS signature of the deposit message. | [types.ts:315](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L315) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/DistributedValidator.md b/versioned_docs/version-v1.9/sdk/type-aliases/DistributedValidator.md new file mode 100644 index 0000000000..3cfcaf064e --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/DistributedValidator.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "DistributedValidator" +slug: /sdk/type-aliases/distributedvalidator +--- + +# DistributedValidator + +> **DistributedValidator** = `object` + +Defined in: [types.ts:321](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L321) + +Required deposit data for validator activation + +## Properties + +| Property | Type | Description | Defined in | +| ------------------------ | ----------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `distributed_public_key` | `string` | The public key of the distributed validator. | [types.ts:323](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L323) | +| `public_shares` | `string`\[] | The public key of the node distributed validator share. | [types.ts:326](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L326) | +| `deposit_data?` | `Partial`<[`DepositData`](DepositData.md)> | The deposit data for activating the DV. | [types.ts:329](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L329) | +| `partial_deposit_data?` | `Partial`<[`DepositData`](DepositData.md)>\[] | The deposit data with partial amounts or full amount for activating the DV. | [types.ts:332](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L332) | +| `builder_registration?` | [`BuilderRegistration`](BuilderRegistration.md) | pre-generated signed validator builder registration to be sent to builder network. | [types.ts:335](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L335) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/EOADepositPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/EOADepositPayload.md new file mode 100644 index 0000000000..35d1490605 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/EOADepositPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "EOADepositPayload" +slug: /sdk/type-aliases/eoadepositpayload +unlisted: true +--- + +# EOADepositPayload + +> **EOADepositPayload** = `object` + +Defined in: [types.ts:673](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L673) + +Payload for depositing to batch deposit contract + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `deposits` | `object`[] | Array of deposit objects | [types.ts:675](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L675) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/EOAWithdrawalPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/EOAWithdrawalPayload.md new file mode 100644 index 0000000000..b32dcf54bb --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/EOAWithdrawalPayload.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "EOAWithdrawalPayload" +slug: /sdk/type-aliases/eoawithdrawalpayload +unlisted: true +--- + +# EOAWithdrawalPayload + +> **EOAWithdrawalPayload** = `object` + +Defined in: [types.ts:637](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L637) + +Payload for requesting withdrawal from EOA contract + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `pubkey` | `string` | Validator public key in hex format | [types.ts:639](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L639) | +| `allocation` | `number` | Withdrawal amount in ETH | [types.ts:642](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L642) | +| `requiredFee` | `string` | Required fee in wei | [types.ts:645](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L645) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ETH_ADDRESS.md b/versioned_docs/version-v1.9/sdk/type-aliases/ETH_ADDRESS.md new file mode 100644 index 0000000000..db402d930a --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ETH_ADDRESS.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "ETH_ADDRESS" +slug: /sdk/type-aliases/eth_address +--- + +# ETH\_ADDRESS + +> **ETH\_ADDRESS** = `string` + +Defined in: [types.ts:381](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L381) + +String expected to be Ethereum Address diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/HttpRequestFunc.md b/versioned_docs/version-v1.9/sdk/type-aliases/HttpRequestFunc.md new file mode 100644 index 0000000000..a8cbe0f159 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/HttpRequestFunc.md @@ -0,0 +1,29 @@ +--- +sidebar_label: "HttpRequestFunc()" +slug: /sdk/type-aliases/httprequestfunc +unlisted: true +--- + +# HttpRequestFunc() + +> **HttpRequestFunc** = (`url`, `config?`) => `Promise`\<`any`\> + +Defined in: [types.ts:558](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L558) + +Generic HTTP request function type. +Args: + url: string - The URL to request. + config?: Record\ - Optional request configuration (e.g., method, headers, body for POST). +Returns: + Promise\ - The response data. + +## Parameters + +| Parameter | Type | +| ------ | ------ | +| `url` | `string` | +| `config?` | `Record`\<`string`, `any`\> | + +## Returns + +`Promise`\<`any`\> diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMArgs.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMArgs.md new file mode 100644 index 0000000000..4cfb912acc --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMArgs.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "OVMArgs" +slug: /sdk/type-aliases/ovmargs +unlisted: true +--- + +# OVMArgs + +> **OVMArgs** = `object` + +Defined in: [types.ts:566](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L566) + +OVM Arguments for contract creation + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `OVMOwnerAddress` | `string` | Owner address for the OVM contract. | [types.ts:568](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L568) | +| `principalRecipient` | `string` | Principal recipient address. | [types.ts:571](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L571) | +| `rewardRecipient` | `string` | Rewards recipient of the cluster. | [types.ts:574](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L574) | +| `principalThreshold` | `number` | Principal threshold in ETH for OVM contract. | [types.ts:577](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L577) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMBaseSplitPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMBaseSplitPayload.md new file mode 100644 index 0000000000..92e630877b --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMBaseSplitPayload.md @@ -0,0 +1,23 @@ +--- +sidebar_label: "OVMBaseSplitPayload" +slug: /sdk/type-aliases/ovmbasesplitpayload +unlisted: true +--- + +# OVMBaseSplitPayload + +> **OVMBaseSplitPayload** = `object` + +Defined in: [types.ts:207](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L207) + +OVM and SplitV2 Base Params + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `rewardSplitRecipients` | [`SplitV2Recipient`](SplitV2Recipient.md)[] | The split recipients addresses and splits. | [types.ts:209](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L209) | +| `OVMOwnerAddress` | `string` | Owner address for the OVM contract. | [types.ts:212](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L212) | +| `splitOwnerAddress?` | `string` | Owner address for the splitter contracts. | [types.ts:215](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L215) | +| `principalThreshold?` | `number` | Principal threshold in ETH for OVM contract. | [types.ts:218](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L218) | +| `distributorFeePercent?` | `number` | Distributor fee percentage (0-10). | [types.ts:221](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L221) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMDepositPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMDepositPayload.md new file mode 100644 index 0000000000..e8bed51054 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMDepositPayload.md @@ -0,0 +1,20 @@ +--- +sidebar_label: "OVMDepositPayload" +slug: /sdk/type-aliases/ovmdepositpayload +unlisted: true +--- + +# OVMDepositPayload + +> **OVMDepositPayload** = `object` + +Defined in: [types.ts:651](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L651) + +Payload for depositing to OVM contract with multicall3 + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `ovmAddress` | `string` | OVM contract address | [types.ts:653](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L653) | +| `deposits` | `object`[] | Array of deposit objects | [types.ts:656](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L656) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMRequestWithdrawalPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMRequestWithdrawalPayload.md new file mode 100644 index 0000000000..fac62c4c85 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMRequestWithdrawalPayload.md @@ -0,0 +1,22 @@ +--- +sidebar_label: "OVMRequestWithdrawalPayload" +slug: /sdk/type-aliases/ovmrequestwithdrawalpayload +unlisted: true +--- + +# OVMRequestWithdrawalPayload + +> **OVMRequestWithdrawalPayload** = `object` + +Defined in: [types.ts:620](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L620) + +Payload for requesting withdrawal from OVM contract + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `withdrawalFees` | `string` | request withdrawal fees in wei | [types.ts:622](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L622) | +| `ovmAddress` | `string` | OVM contract address | [types.ts:625](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L625) | +| `pubKeys` | `string`[] | Array of validator public keys in bytes format | [types.ts:628](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L628) | +| `amounts` | `string`[] | Array of withdrawal amounts in gwei (uint64) as strings | [types.ts:631](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L631) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMRewardsSplitPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMRewardsSplitPayload.md new file mode 100644 index 0000000000..3209f9ab1f --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMRewardsSplitPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "OVMRewardsSplitPayload" +slug: /sdk/type-aliases/ovmrewardssplitpayload +unlisted: true +--- + +# OVMRewardsSplitPayload + +> **OVMRewardsSplitPayload** = [`OVMBaseSplitPayload`](OVMBaseSplitPayload.md) & `object` + +Defined in: [types.ts:227](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L227) + +OVM and SplitV2 Params for rewards-only split + +## Type Declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `principalRecipient` | `string` | Principal recipient address (single address for rewards-only split). | [types.ts:229](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L229) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMSplitPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMSplitPayload.md new file mode 100644 index 0000000000..75fa7ed20f --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMSplitPayload.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "OVMSplitPayload" +slug: /sdk/type-aliases/ovmsplitpayload +unlisted: true +--- + +# OVMSplitPayload + +> **OVMSplitPayload** = [`OVMRewardsSplitPayload`](OVMRewardsSplitPayload.md) \| [`OVMTotalSplitPayload`](OVMTotalSplitPayload.md) + +Defined in: [types.ts:243](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L243) + +Union type for both OVM split scenarios diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OVMTotalSplitPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OVMTotalSplitPayload.md new file mode 100644 index 0000000000..88297e78fd --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OVMTotalSplitPayload.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "OVMTotalSplitPayload" +slug: /sdk/type-aliases/ovmtotalsplitpayload +unlisted: true +--- + +# OVMTotalSplitPayload + +> **OVMTotalSplitPayload** = [`OVMBaseSplitPayload`](OVMBaseSplitPayload.md) & `object` + +Defined in: [types.ts:235](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L235) + +OVM and SplitV2 Params for total split scenario + +## Type Declaration + +| Name | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `principalSplitRecipients` | [`SplitV2Recipient`](SplitV2Recipient.md)[] | Principal recipients addresses and splits (array for total split scenario). | [types.ts:237](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L237) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OWRTranches.md b/versioned_docs/version-v1.9/sdk/type-aliases/OWRTranches.md new file mode 100644 index 0000000000..28d76a6e1e --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OWRTranches.md @@ -0,0 +1,21 @@ +--- +sidebar_label: "OWRTranches" +slug: /sdk/type-aliases/owrtranches +unlisted: true +--- + +# OWRTranches + +> **OWRTranches** = `object` + +Defined in: [types.ts:259](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L259) + +OWR Tranches + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `principalRecipient` | [`ETH_ADDRESS`](ETH_ADDRESS.md) | Address that will reclaim validator principal after exit. | [types.ts:261](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L261) | +| `rewardRecipient` | [`ETH_ADDRESS`](ETH_ADDRESS.md) | Address that will reclaim validator rewards during operation. | [types.ts:264](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L264) | +| `amountOfPrincipalStake` | `number` | Amount of principal staked. | [types.ts:267](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L267) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/OperatorPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/OperatorPayload.md new file mode 100644 index 0000000000..fd48b714fc --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/OperatorPayload.md @@ -0,0 +1,12 @@ +--- +sidebar_label: "OperatorPayload" +slug: /sdk/type-aliases/operatorpayload +--- + +# OperatorPayload + +> **OperatorPayload** = `Partial`<[`ClusterOperator`](ClusterOperator.md)> & `Required`<`Pick`<[`ClusterOperator`](ClusterOperator.md), `"enr"` | `"version"`>> + +Defined in: [types.ts:68](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L68) + +A partial view of `ClusterOperator` with `enr` and `version` as required properties. diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/ProviderType.md b/versioned_docs/version-v1.9/sdk/type-aliases/ProviderType.md new file mode 100644 index 0000000000..a1d061727c --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/ProviderType.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "ProviderType" +slug: /sdk/type-aliases/providertype +unlisted: true +--- + +# ProviderType + +> **ProviderType** = `Provider` \| `JsonRpcProvider` \| `JsonRpcApiProvider` \| `ethers.BrowserProvider` + +Defined in: [types.ts:386](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L386) + +Provider Types diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/README.md b/versioned_docs/version-v1.9/sdk/type-aliases/README.md new file mode 100644 index 0000000000..bf0d8a2b37 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Type-Aliases" +slug: /sdk/type-aliases +--- + +# Type-Aliases + diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/SafeRpcUrl.md b/versioned_docs/version-v1.9/sdk/type-aliases/SafeRpcUrl.md new file mode 100644 index 0000000000..25f2a4b2a8 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/SafeRpcUrl.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "SafeRpcUrl" +slug: /sdk/type-aliases/saferpcurl +unlisted: true +--- + +# SafeRpcUrl + +> **SafeRpcUrl** = `string` + +Defined in: [types.ts:395](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L395) + +Safe Wallet Provider Types diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/SignerType.md b/versioned_docs/version-v1.9/sdk/type-aliases/SignerType.md new file mode 100644 index 0000000000..6ab97e44f0 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/SignerType.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "SignerType" +slug: /sdk/type-aliases/signertype +unlisted: true +--- + +# SignerType + +> **SignerType** = `JsonRpcSigner` \| `Wallet` + +Defined in: [types.ts:400](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L400) + +Signer Types diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/SplitRecipient.md b/versioned_docs/version-v1.9/sdk/type-aliases/SplitRecipient.md new file mode 100644 index 0000000000..0429019cb4 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/SplitRecipient.md @@ -0,0 +1,19 @@ +--- +sidebar_label: "SplitRecipient" +slug: /sdk/type-aliases/splitrecipient +--- + +# SplitRecipient + +> **SplitRecipient** = `object` + +Defined in: [types.ts:165](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L165) + +Split Recipient Keys + +## Properties + +| Property | Type | Description | Defined in | +| ------------------- | -------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `account` | `string` | The split recipient address. | [types.ts:167](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L167) | +| `percentAllocation` | `number` | The recipient split. | [types.ts:170](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L170) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/SplitV2Recipient.md b/versioned_docs/version-v1.9/sdk/type-aliases/SplitV2Recipient.md new file mode 100644 index 0000000000..44997b67dd --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/SplitV2Recipient.md @@ -0,0 +1,20 @@ +--- +sidebar_label: "SplitV2Recipient" +slug: /sdk/type-aliases/splitv2recipient +unlisted: true +--- + +# SplitV2Recipient + +> **SplitV2Recipient** = `object` + +Defined in: [types.ts:248](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L248) + +SplitV2 Recipient structure + +## Properties + +| Property | Type | Description | Defined in | +| ------ | ------ | ------ | ------ | +| `address` | `string` | Recipient address. | [types.ts:250](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L250) | +| `percentAllocation` | `number` | Percentage allocation (0-100 with up to 4 decimals). | [types.ts:253](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L253) | diff --git a/versioned_docs/version-v1.9/sdk/type-aliases/TotalSplitPayload.md b/versioned_docs/version-v1.9/sdk/type-aliases/TotalSplitPayload.md new file mode 100644 index 0000000000..e419e5fcb8 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/type-aliases/TotalSplitPayload.md @@ -0,0 +1,25 @@ +--- +sidebar_label: "TotalSplitPayload" +slug: /sdk/type-aliases/totalsplitpayload +--- + +# TotalSplitPayload + +> **TotalSplitPayload** = `object` + +Defined in: [types.ts:176](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L176) + +Split Proxy Params + +## Extended by + +* [`RewardsSplitPayload`](../interfaces/RewardsSplitPayload.md) + +## Properties + +| Property | Type | Description | Defined in | +| -------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `splitRecipients` | [`SplitRecipient`](SplitRecipient.md)\[] | The split recipients addresses and splits. | [types.ts:178](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L178) | +| `ObolRAFSplit?` | `number` | Split percentageNumber allocated for obol retroactive funding, minimum is 1%. | [types.ts:181](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L181) | +| `distributorFee?` | `number` | The percentageNumber of accrued rewards that is paid to the caller of the distribution function to compensate them for the gas costs of doing so. Cannot be greater than 10%. For example, 5 represents 5%. | [types.ts:184](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L184) | +| `controllerAddress?` | `string` | Address that can mutate the split, should be ZeroAddress for immutable split. | [types.ts:187](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/types.ts#L187) | diff --git a/versioned_docs/version-v1.9/sdk/variables/CAPELLA_FORK_MAPPING.md b/versioned_docs/version-v1.9/sdk/variables/CAPELLA_FORK_MAPPING.md new file mode 100644 index 0000000000..cbf011fe35 --- /dev/null +++ b/versioned_docs/version-v1.9/sdk/variables/CAPELLA_FORK_MAPPING.md @@ -0,0 +1,14 @@ +--- +sidebar_label: "CAPELLA_FORK_MAPPING" +slug: /sdk/variables/capella_fork_mapping +unlisted: true +--- + +# CAPELLA\_FORK\_MAPPING + +> `const` **CAPELLA\_FORK\_MAPPING**: `Record`\<`string`, `string`\> + +Defined in: [constants.ts:292](https://github.com/ObolNetwork/obol-sdk/blob/5137bd5c4ded55a50234f19135ea3a5bfeab4d47/src/constants.ts#L292) + +Maps base fork versions to their corresponding Capella fork versions. +Example: Mainnet Capella fork version. diff --git a/versioned_docs/version-v1.9/walkthrough-guides/walkthroughs/README.md b/versioned_docs/version-v1.9/walkthrough-guides/walkthroughs/README.md new file mode 100644 index 0000000000..65c6fe2fea --- /dev/null +++ b/versioned_docs/version-v1.9/walkthrough-guides/walkthroughs/README.md @@ -0,0 +1,7 @@ +--- +sidebar_label: "Walkthroughs" +slug: /walkthrough-guides/walkthroughs +--- + +# Walkthroughs + diff --git a/versioned_docs/version-v1.9/walkthrough-guides/walkthroughs/walkthrough-guides.md b/versioned_docs/version-v1.9/walkthrough-guides/walkthroughs/walkthrough-guides.md new file mode 100644 index 0000000000..461dff576f --- /dev/null +++ b/versioned_docs/version-v1.9/walkthrough-guides/walkthroughs/walkthrough-guides.md @@ -0,0 +1,35 @@ +--- +description: "Walkthrough guides" +sidebar_label: "Walkthrough Guides" +slug: /walkthrough-guides/walkthroughs/walkthrough-guides +--- + +# Walkthrough Guides + +This section contains walkthrough guides for beginner users. Some of these guides are specific to particular hardware or operating systems, and may not replace more general documentation. These guides contain more detailed step-by-step information which may be useful for beginner users with limited experience with Linux, validators, and other topics which the primary guides assume some prior familiarity of. + +Some of these guides are community-created, and may contain issues or omissions. + +## Running Charon with Native Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-native.md). + +This guide covers running Charon with local EC/BN running as system service (systemd). For example, if you have followed one of these guides (Somer Esat Guides / CoinCashew Guides / EthPilar) to set up your node. + +## Running Charon with Docker Execution/Consensus Clients - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_local-docker.md). + +This guide covers running Charon with local EC/BN managed by a docker-based stack (ETH-Docker/Rocket Pool Smart Node). + +## Running Charon with remote EC/BN - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_remote.md). + +This guide covers running Charon with remote EC/BN. For people who already have EC/BN running on a remote/differnt machine, and want to run Charon separately (for example a small VPS). + +## Running Multiple Charon instances on one machine - by Atomic Whale + +See the guide [here](https://github.com/atomicwhale/obol-guides/blob/main/charon_multiple.md). + +This guide covers steps to run multiple Charon instaces on one machine. diff --git a/versioned_sidebars/version-v1.3-sidebars.json b/versioned_sidebars/version-v1.3-sidebars.json new file mode 100644 index 0000000000..d066fd9788 --- /dev/null +++ b/versioned_sidebars/version-v1.3-sidebars.json @@ -0,0 +1,731 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum-and-its-relationship-with-dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/community-testing", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer-score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/useful-links", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics to Obol Monitoring" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Governance", + "link": { + "type": "doc", + "id": "community-and-governance/governance/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/collective", + "label": "Collective Overview" + }, + { + "type": "doc", + "id": "community-and-governance/governance/token-house", + "label": "The Token House" + }, + { + "type": "doc", + "id": "community-and-governance/governance/raf", + "label": "The RAF" + }, + { + "type": "doc", + "id": "community-and-governance/governance/obol-token", + "label": "The OBOL Token" + }, + { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide", + "label": "Delegate Guide" + }, + { + "type": "doc", + "id": "community-and-governance/governance/raf1-guide", + "label": "RAF1 Guide" + }, + { + "type": "category", + "label": "Grants Program", + "link": { + "type": "doc", + "id": "community-and-governance/governance/grants-program/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook", + "label": "How to create a proposal in Questbook?" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption", + "label": "Grant Track for Boosting Obol DV Adoption" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth", + "label": "Grant Track for Strengthening the Collective: Operators & Community Growth" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance", + "label": "Grant Track for Establishing OBOL Token’s Role in DeFi & Governance" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-optimizing-decentralized-governance", + "label": "Grant Track for Optimizing Decentralized Governance" + } + ] + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program" + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versioned_sidebars/version-v1.4-sidebars.json b/versioned_sidebars/version-v1.4-sidebars.json new file mode 100644 index 0000000000..f52080a88e --- /dev/null +++ b/versioned_sidebars/version-v1.4-sidebars.json @@ -0,0 +1,766 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum-and-its-relationship-with-dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/community-testing", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer-score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/useful-links", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics to Obol Monitoring" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/beacon-node-authentication", + "label": "Beacon node authentication" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Governance", + "link": { + "type": "doc", + "id": "community-and-governance/governance/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/collective", + "label": "Collective Overview" + }, + { + "type": "doc", + "id": "community-and-governance/governance/token-house", + "label": "The Token House" + }, + { + "type": "category", + "label": "The RAF", + "link": { + "type": "doc", + "id": "community-and-governance/governance/raf/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/raf/raf-1", + "label": "RAF #1" + } + ] + }, + { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide", + "label": "Delegate Guide" + }, + { + "type": "category", + "label": "Grants Program", + "link": { + "type": "doc", + "id": "community-and-governance/governance/grants-program/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook", + "label": "How to create a proposal in Questbook?" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption", + "label": "Grant Track for Boosting Obol DV Adoption" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth", + "label": "Grant Track for Strengthening the Collective: Operators & Community Growth" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance", + "label": "Grant Track for Establishing OBOL Token’s Role in DeFi & Governance" + } + ] + } + ] + }, + { + "type": "category", + "label": "The OBOL Token", + "link": { + "type": "doc", + "id": "community-and-governance/obol-token/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/obol-token/token-utility", + "label": "Token Utility" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/staking-and-stobol", + "label": "Staking & stOBOL" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-distribution-and-liquidity", + "label": "Token Distribution & Liquidity" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-holders-faq", + "label": "Token Holders FAQ" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/tge-faq", + "label": "TGE FAQ" + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program" + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versioned_sidebars/version-v1.5-sidebars.json b/versioned_sidebars/version-v1.5-sidebars.json new file mode 100644 index 0000000000..a32a91e70c --- /dev/null +++ b/versioned_sidebars/version-v1.5-sidebars.json @@ -0,0 +1,776 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum-and-its-relationship-with-dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/community-testing", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer-score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/useful-links", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics to Obol Monitoring" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/beacon-node-authentication", + "label": "Beacon node authentication" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Governance", + "link": { + "type": "doc", + "id": "community-and-governance/governance/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/collective", + "label": "Collective Overview" + }, + { + "type": "doc", + "id": "community-and-governance/governance/token-house", + "label": "The Token House" + }, + { + "type": "category", + "label": "The RAF", + "link": { + "type": "doc", + "id": "community-and-governance/governance/raf/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/raf/raf1-guide", + "label": "RAF #1" + } + ] + }, + { + "type": "category", + "label": "Delegate Guide", + "link": { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation", + "label": "Delegate Reputation Score & Compensation" + } + ] + }, + { + "type": "category", + "label": "Grants Program", + "link": { + "type": "doc", + "id": "community-and-governance/governance/grants-program/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/how-to-create-a-proposal-in-questbook", + "label": "How to create a proposal in Questbook?" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-boosting-obol-dv-adoption", + "label": "Grant Track for Boosting Obol DV Adoption" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-strengthening-the-collective-operators-and-community-growth", + "label": "Grant Track for Strengthening the Collective: Operators & Community Growth" + }, + { + "type": "doc", + "id": "community-and-governance/governance/grants-program/grant-track-for-establishing-obol-tokens-role-in-defi-and-governance", + "label": "Grant Track for Establishing OBOL Token’s Role in DeFi & Governance" + } + ] + } + ] + }, + { + "type": "category", + "label": "The OBOL Token", + "link": { + "type": "doc", + "id": "community-and-governance/obol-token/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/obol-token/token-utility", + "label": "Token Utility" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/staking-and-stobol", + "label": "Staking & stOBOL" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-distribution-and-liquidity", + "label": "Token Distribution & Liquidity" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-holders-faq", + "label": "Token Holders FAQ" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/tge-faq", + "label": "TGE FAQ" + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program" + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versioned_sidebars/version-v1.6-sidebars.json b/versioned_sidebars/version-v1.6-sidebars.json new file mode 100644 index 0000000000..412cfdf5c3 --- /dev/null +++ b/versioned_sidebars/version-v1.6-sidebars.json @@ -0,0 +1,816 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum_and_dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/testnet", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer_score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/resources", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics to Obol Monitoring" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/beacon-node-authentication", + "label": "Beacon node authentication" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/add-validators", + "label": "Adding Validators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/custom-graffiti", + "label": "Custom Graffiti" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-tls-protocol", + "label": "Enable TLS Protocol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/fallback-beacon-nodes", + "label": "Fallback Beacon Nodes" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/nicknames", + "label": "Nicknames" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/client-swap", + "label": "Client Swap" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Governance", + "link": { + "type": "doc", + "id": "community-and-governance/governance/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/collective", + "label": "Collective Overview" + }, + { + "type": "doc", + "id": "community-and-governance/governance/token-house", + "label": "The Token House" + }, + { + "type": "category", + "label": "The RAF", + "link": { + "type": "doc", + "id": "community-and-governance/governance/raf/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/raf/raf1-guide", + "label": "RAF #1" + } + ] + }, + { + "type": "category", + "label": "Delegate Guide", + "link": { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation", + "label": "Delegate Reputation Score & Compensation" + } + ] + } + ] + }, + { + "type": "category", + "label": "The OBOL Token", + "link": { + "type": "doc", + "id": "community-and-governance/obol-token/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/obol-token/token-utility", + "label": "Token Utility" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/staking-and-stobol", + "label": "Staking & stOBOL" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/wstobol", + "label": "wstOBOL" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-distribution-and-liquidity", + "label": "Token Distribution & Liquidity" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-holders-faq", + "label": "Token Holders FAQ" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/tge-faq", + "label": "TGE FAQ" + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "category", + "label": "Grants Program", + "link": { + "type": "doc", + "id": "community-and-governance/community/grants-program/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-staking-masters", + "label": "Grants Track for Staking Masters" + }, + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-community-events", + "label": "Grants Track for Community Events" + }, + { + "type": "category", + "label": "Grants Track for Open Strategic Missions", + "link": { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions", + "label": "Strategic Open Missions" + } + ] + } + ] + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + }, + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program (Archived)" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versioned_sidebars/version-v1.7-sidebars.json b/versioned_sidebars/version-v1.7-sidebars.json new file mode 100644 index 0000000000..642de7a529 --- /dev/null +++ b/versioned_sidebars/version-v1.7-sidebars.json @@ -0,0 +1,821 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum_and_dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/testnet", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer_score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/resources", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics to Obol Monitoring" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/beacon-node-authentication", + "label": "Beacon node authentication" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/add-validators", + "label": "Adding Validators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/custom-graffiti", + "label": "Custom Graffiti" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-tls-protocol", + "label": "Enable TLS Protocol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/fallback-beacon-nodes", + "label": "Fallback Beacon Nodes" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/nicknames", + "label": "Nicknames" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/operator-rotation", + "label": "Operator Rotation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/client-swap", + "label": "Client Swap" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Governance", + "link": { + "type": "doc", + "id": "community-and-governance/governance/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/collective", + "label": "Collective Overview" + }, + { + "type": "doc", + "id": "community-and-governance/governance/token-house", + "label": "The Token House" + }, + { + "type": "category", + "label": "The RAF", + "link": { + "type": "doc", + "id": "community-and-governance/governance/raf/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/raf/raf1-guide", + "label": "RAF #1" + } + ] + }, + { + "type": "category", + "label": "Delegate Guide", + "link": { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation", + "label": "Delegate Reputation Score & Compensation" + } + ] + } + ] + }, + { + "type": "category", + "label": "The OBOL Token", + "link": { + "type": "doc", + "id": "community-and-governance/obol-token/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/obol-token/token-utility", + "label": "Token Utility" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/staking-and-stobol", + "label": "Staking & stOBOL" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/wstobol", + "label": "wstOBOL" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-distribution-and-liquidity", + "label": "Token Distribution & Liquidity" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-holders-faq", + "label": "Token Holders FAQ" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/tge-faq", + "label": "TGE FAQ" + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "category", + "label": "Grants Program", + "link": { + "type": "doc", + "id": "community-and-governance/community/grants-program/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-staking-masters", + "label": "Grants Track for Staking Masters" + }, + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-community-events", + "label": "Grants Track for Community Events" + }, + { + "type": "category", + "label": "Grants Track for Open Strategic Missions", + "link": { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions", + "label": "Strategic Open Missions" + } + ] + } + ] + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + }, + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program (Archived)" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versioned_sidebars/version-v1.8-sidebars.json b/versioned_sidebars/version-v1.8-sidebars.json new file mode 100644 index 0000000000..e5e6a05b63 --- /dev/null +++ b/versioned_sidebars/version-v1.8-sidebars.json @@ -0,0 +1,937 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum_and_dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/testnet", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer_score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/resources", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics to Obol Monitoring" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "category", + "label": "Create a Lido stVault", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/lido-v3-stvault-integration-kit" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/lido-v3-stvault-for-node-operator", + "label": "For Node Operators" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-v3-stvault-for-capital-allocators", + "label": "For Capital Allocators" + } + ] + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "Run a DV on a DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/client-swap", + "label": "Swapping Clients" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/add-validators", + "label": "Adding Validators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/add-operators", + "label": "Adding Operators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/remove-operators", + "label": "Removing Operators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/replace-operator", + "label": "Replace an Operator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/recreate-private-keys", + "label": "Recreating Private Keys" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/operator-rotation", + "label": "Operator Rotation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/beacon-node-authentication", + "label": "Beacon node authentication" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/add-validators", + "label": "Adding Validators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/add-operators", + "label": "Adding Operators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/remove-operators", + "label": "Removing Operators" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/replace-operator", + "label": "Replacing Operator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/recreate-private-keys", + "label": "Recreating Private Keys" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/alter-withdrawal-addresses", + "label": "Alter Withdrawal Addresses" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/custom-graffiti", + "label": "Custom Graffiti" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-tls-protocol", + "label": "Enable TLS Protocol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/fallback-beacon-nodes", + "label": "Fallback Beacon Nodes" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/nicknames", + "label": "Nicknames" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/custom-graffiti", + "label": "Custom Graffiti" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-tls-protocol", + "label": "Enable TLS Protocol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Governance", + "link": { + "type": "doc", + "id": "community-and-governance/governance/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/collective", + "label": "Collective Overview" + }, + { + "type": "doc", + "id": "community-and-governance/governance/token-house", + "label": "The Token House" + }, + { + "type": "category", + "label": "The RAF", + "link": { + "type": "doc", + "id": "community-and-governance/governance/raf/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/raf/raf1-guide", + "label": "RAF #1" + } + ] + }, + { + "type": "category", + "label": "Delegate Guide", + "link": { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/governance/delegate-guide/delegate-reputation-score-and-compensation", + "label": "Delegate Reputation Score & Compensation" + } + ] + } + ] + }, + { + "type": "category", + "label": "The OBOL Token", + "link": { + "type": "doc", + "id": "community-and-governance/obol-token/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/obol-token/token-distribution-and-liquidity", + "label": "Token Distribution & Liquidity" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/token-holders-faq", + "label": "Token Holders FAQ" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/tge-faq", + "label": "TGE FAQ" + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "category", + "label": "Grants Program", + "link": { + "type": "doc", + "id": "community-and-governance/community/grants-program/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-staking-masters", + "label": "Grants Track for Staking Masters" + }, + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-community-events", + "label": "Grants Track for Community Events" + }, + { + "type": "category", + "label": "Grants Track for Open Strategic Missions", + "link": { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program/grants-track-for-open-strategic-missions/strategic-open-missions", + "label": "Strategic Open Missions" + } + ] + } + ] + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + }, + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program (Archived)" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Obol Stack", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "obol-stack/README", + "label": "Introduction" + }, + { + "type": "doc", + "id": "obol-stack/quickstart", + "label": "Quickstart" + }, + { + "type": "doc", + "id": "obol-stack/installing-networks", + "label": "Installing Networks" + }, + { + "type": "doc", + "id": "obol-stack/installing-apps", + "label": "Installing Apps" + }, + { + "type": "doc", + "id": "obol-stack/faq", + "label": "FAQ" + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/dv-migrate", + "label": "DV Migrate" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/deposit-data", + "label": "Deposit Data" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "doc", + "id": "api/test", + "label": "Test" + }, + { + "type": "doc", + "id": "api/tvs", + "label": "TVS" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versioned_sidebars/version-v1.9-sidebars.json b/versioned_sidebars/version-v1.9-sidebars.json new file mode 100644 index 0000000000..94c9f4b0fa --- /dev/null +++ b/versioned_sidebars/version-v1.9-sidebars.json @@ -0,0 +1,857 @@ +{ + "docs": [ + { + "type": "html", + "value": "Learn", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Introduction", + "link": { + "type": "doc", + "id": "README" + }, + "items": [ + { + "type": "doc", + "id": "learn/introduction/learn-about-obol/README", + "label": "Learn About Obol" + }, + { + "type": "doc", + "id": "learn/intro/obol-collective", + "label": "Obol Collective" + }, + { + "type": "doc", + "id": "learn/intro/obol-incentives", + "label": "OBOL Incentives" + }, + { + "type": "doc", + "id": "learn/intro/key-concepts", + "label": "Key Staking Concepts" + }, + { + "type": "doc", + "id": "learn/intro/obol-vs-others", + "label": "Obol vs Other DV Implementations" + }, + { + "type": "doc", + "id": "learn/intro/obol-splits", + "label": "Obol Splits" + }, + { + "type": "doc", + "id": "learn/intro/launchpad", + "label": "DV Launchpad" + }, + { + "type": "doc", + "id": "learn/intro/frequently-asked-questions", + "label": "Frequently Asked Questions" + } + ] + }, + { + "type": "category", + "label": "Charon", + "link": { + "type": "doc", + "id": "learn/charon/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/charon/intro", + "label": "Introduction to Charon" + }, + { + "type": "doc", + "id": "learn/charon/dkg", + "label": "Distributed Key Generation" + }, + { + "type": "doc", + "id": "learn/charon/cluster-configuration", + "label": "Cluster Configuration" + }, + { + "type": "doc", + "id": "learn/charon/charon-networking", + "label": "Charon Networking" + }, + { + "type": "doc", + "id": "learn/charon/charon-cli-reference", + "label": "CLI Reference" + } + ] + }, + { + "type": "category", + "label": "Further Reading", + "link": { + "type": "doc", + "id": "learn/further-reading/README" + }, + "items": [ + { + "type": "doc", + "id": "learn/further-reading/ethereum_and_dvt", + "label": "Ethereum and Its Relationship With DVT" + }, + { + "type": "doc", + "id": "learn/further-reading/testnet", + "label": "Community Testing" + }, + { + "type": "doc", + "id": "learn/further-reading/peer_score", + "label": "Peer Score" + }, + { + "type": "doc", + "id": "learn/further-reading/resources", + "label": "Useful Links" + } + ] + }, + { + "type": "html", + "value": "Run a DV", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Quickstart", + "link": { + "type": "doc", + "id": "run-a-dv/start/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/start/quickstart_overview", + "label": "Quickstart Overview" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-alone", + "label": "Create a DV Alone" + }, + { + "type": "doc", + "id": "run-a-dv/start/create-a-dv-with-a-group", + "label": "Create a DV With a Group" + }, + { + "type": "doc", + "id": "run-a-dv/start/obol-monitoring", + "label": "Push Metrics and Logs to Obol" + } + ] + }, + { + "type": "category", + "label": "Prepare to Run a DV", + "link": { + "type": "doc", + "id": "run-a-dv/prepare/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/prepare/how_where_dvs", + "label": "How and Where To Run DVs" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/deployment-best-practices", + "label": "Deployment Best Practices" + }, + { + "type": "doc", + "id": "run-a-dv/prepare/test-a-cluster", + "label": "Test a Cluster" + } + ] + }, + { + "type": "category", + "label": "Running a DV", + "link": { + "type": "doc", + "id": "run-a-dv/running/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/running/activate-a-dv", + "label": "Activate a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/request-withdrawal", + "label": "Request Withdrawal" + }, + { + "type": "doc", + "id": "run-a-dv/running/distribute-rewards", + "label": "Distribute Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/claim-rewards", + "label": "Claim Rewards" + }, + { + "type": "doc", + "id": "run-a-dv/running/update-a-dv", + "label": "Update a DV" + }, + { + "type": "doc", + "id": "run-a-dv/running/monitoring", + "label": "Monitoring Your Node" + }, + { + "type": "doc", + "id": "run-a-dv/running/exit-a-dv", + "label": "Exit a DV" + } + ] + }, + { + "type": "category", + "label": "Edit a Cluster", + "link": { + "type": "doc", + "id": "run-a-dv/editing/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/editing/add-validators", + "label": "Adding Validators" + }, + { + "type": "doc", + "id": "run-a-dv/editing/add-operators", + "label": "Adding Operators" + }, + { + "type": "doc", + "id": "run-a-dv/editing/remove-operators", + "label": "Removing Operators" + }, + { + "type": "doc", + "id": "run-a-dv/editing/replace-operator", + "label": "Replace an Operator" + }, + { + "type": "doc", + "id": "run-a-dv/editing/recreate-private-keys", + "label": "Recreating Private Keys" + } + ] + }, + { + "type": "category", + "label": "Partner Integrations", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/README" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/create-an-eigenlayer-dv", + "label": "Create an EigenLayer DV" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-csm", + "label": "Create a Lido CSM DV" + }, + { + "type": "category", + "label": "Create a Lido stVault", + "link": { + "type": "doc", + "id": "run-a-dv/integrations/lido-v3-stvault-integration-kit" + }, + "items": [ + { + "type": "doc", + "id": "run-a-dv/integrations/lido-v3-stvault-for-node-operator", + "label": "For Node Operators" + }, + { + "type": "doc", + "id": "run-a-dv/integrations/lido-v3-stvault-for-capital-allocators", + "label": "For Capital Allocators" + } + ] + }, + { + "type": "doc", + "id": "run-a-dv/integrations/dappnode", + "label": "Run a DV on a DappNode" + } + ] + }, + { + "type": "html", + "value": "Advanced & Troubleshooting", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Advanced Guides", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/client-swap", + "label": "Swapping Clients" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/operator-rotation", + "label": "Operator Rotation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-split", + "label": "Migrate an Existing Validator" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/create-a-dv-using-the-sdk", + "label": "Create a DV Using the SDK" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/ovm-predeploy", + "label": "Pre-Create a DV with an OVM" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-mev", + "label": "Enable MEV" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/quickstart-combine", + "label": "Combine DV Private Key Shares" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/beacon-node-authentication", + "label": "Beacon node authentication" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/alter-withdrawal-addresses", + "label": "Alter Withdrawal Addresses" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/custom-graffiti", + "label": "Custom Graffiti" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/enable-tls-protocol", + "label": "Enable TLS Protocol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/fallback-beacon-nodes", + "label": "Fallback Beacon Nodes" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/nicknames", + "label": "Set a Nickname" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/self-relay", + "label": "Self-Host a Relay" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/adv-docker-configs", + "label": "Advanced Docker Configs" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/advanced/assign-ovm-roles", + "label": "Assign OVM Roles" + } + ] + }, + { + "type": "category", + "label": "Troubleshooting", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/errors", + "label": "Errors & Resolutions" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/dkg_failure", + "label": "Handling DKG Failure" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/client_configurations", + "label": "Client Configuration" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/troubleshooting/test_command", + "label": "Test Commands" + } + ] + }, + { + "type": "category", + "label": "Security", + "link": { + "type": "doc", + "id": "advanced-and-troubleshooting/security/README" + }, + "items": [ + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/overview", + "label": "Overview" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/risks", + "label": "Centralization Risks and Mitigation" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/bug-bounty", + "label": "Obol Bug Bounty Program" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/smart-contract-audit", + "label": "Smart Contract Audit" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/ev-assessment", + "label": "Software Development at Obol" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/threat_model", + "label": "Charon Threat Model" + }, + { + "type": "doc", + "id": "advanced-and-troubleshooting/security/contact", + "label": "Contacts" + } + ] + }, + { + "type": "html", + "value": "Community & Governance", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "community-and-governance/governance", + "label": "Governance" + }, + { + "type": "category", + "label": "The OBOL Token", + "link": { + "type": "doc", + "id": "community-and-governance/obol-token/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/obol-token/token-distribution-and-liquidity", + "label": "Token Distribution & Liquidity" + }, + { + "type": "doc", + "id": "community-and-governance/obol-token/guide-for-unstaking-obol", + "label": "Guide for Unstaking OBOL" + } + ] + }, + { + "type": "category", + "label": "Community", + "link": { + "type": "doc", + "id": "community-and-governance/community/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/community/grants-program", + "label": "Grants Program" + }, + { + "type": "doc", + "id": "community-and-governance/community/techne", + "label": "Techne" + }, + { + "type": "doc", + "id": "community-and-governance/community/staking-masters", + "label": "Staking Mastery Program (Archived)" + } + ] + }, + { + "type": "category", + "label": "Contribution & Feedback", + "link": { + "type": "doc", + "id": "community-and-governance/contribution/README" + }, + "items": [ + { + "type": "doc", + "id": "community-and-governance/contribution/bug-report", + "label": "Filing a Bug Report" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/docs", + "label": "Documentation Standards" + }, + { + "type": "doc", + "id": "community-and-governance/contribution/feedback", + "label": "Feedback" + } + ] + }, + { + "type": "html", + "value": "Obol Stack", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "obol-stack/README", + "label": "Introduction" + }, + { + "type": "doc", + "id": "obol-stack/quickstart", + "label": "Quickstart" + }, + { + "type": "doc", + "id": "obol-stack/installing-networks", + "label": "Installing Networks" + }, + { + "type": "doc", + "id": "obol-stack/installing-apps", + "label": "Installing Apps" + }, + { + "type": "doc", + "id": "obol-stack/faq", + "label": "FAQ" + }, + { + "type": "html", + "value": "Walkthrough Guides", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "category", + "label": "Walkthroughs", + "link": { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/README" + }, + "items": [ + { + "type": "doc", + "id": "walkthrough-guides/walkthroughs/walkthrough-guides", + "label": "Walkthrough Guides" + } + ] + }, + { + "type": "html", + "value": "SDK", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "sdk/index", + "label": "Intro" + }, + { + "type": "category", + "label": "Enumerations", + "link": { + "type": "doc", + "id": "sdk/enumerations/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/enumerations/FORK_MAPPING", + "label": "FORK_MAPPING" + } + ] + }, + { + "type": "category", + "label": "Classes", + "link": { + "type": "doc", + "id": "sdk/classes/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/classes/Client", + "label": "Client" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "link": { + "type": "doc", + "id": "sdk/interfaces/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/interfaces/ClusterDefinition", + "label": "ClusterDefinition" + }, + { + "type": "doc", + "id": "sdk/interfaces/RewardsSplitPayload", + "label": "RewardsSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Type-Aliases", + "link": { + "type": "doc", + "id": "sdk/type-aliases/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistration", + "label": "BuilderRegistration" + }, + { + "type": "doc", + "id": "sdk/type-aliases/BuilderRegistrationMessage", + "label": "BuilderRegistrationMessage" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterCreator", + "label": "ClusterCreator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterLock", + "label": "ClusterLock" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterOperator", + "label": "ClusterOperator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterPayload", + "label": "ClusterPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ClusterValidator", + "label": "ClusterValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DepositData", + "label": "DepositData" + }, + { + "type": "doc", + "id": "sdk/type-aliases/DistributedValidator", + "label": "DistributedValidator" + }, + { + "type": "doc", + "id": "sdk/type-aliases/ETH_ADDRESS", + "label": "ETH_ADDRESS" + }, + { + "type": "doc", + "id": "sdk/type-aliases/OperatorPayload", + "label": "OperatorPayload" + }, + { + "type": "doc", + "id": "sdk/type-aliases/SplitRecipient", + "label": "SplitRecipient" + }, + { + "type": "doc", + "id": "sdk/type-aliases/TotalSplitPayload", + "label": "TotalSplitPayload" + } + ] + }, + { + "type": "category", + "label": "Functions", + "link": { + "type": "doc", + "id": "sdk/functions/README" + }, + "items": [ + { + "type": "doc", + "id": "sdk/functions/validateClusterLock", + "label": "validateClusterLock" + } + ] + }, + { + "type": "html", + "value": "API", + "className": "sidebar-section-title", + "defaultStyle": true + }, + { + "type": "doc", + "id": "api/what-is-this-api", + "label": "What is this API?" + }, + { + "type": "doc", + "id": "api/system", + "label": "System" + }, + { + "type": "doc", + "id": "api/metrics", + "label": "Metrics" + }, + { + "type": "doc", + "id": "api/cluster-definition", + "label": "Cluster Definition" + }, + { + "type": "doc", + "id": "api/cluster-lock", + "label": "Cluster Lock" + }, + { + "type": "doc", + "id": "api/state", + "label": "State" + }, + { + "type": "doc", + "id": "api/dv-exit", + "label": "DV Exit" + }, + { + "type": "doc", + "id": "api/dv-migrate", + "label": "DV Migrate" + }, + { + "type": "doc", + "id": "api/cluster-effectiveness", + "label": "Cluster Effectiveness" + }, + { + "type": "doc", + "id": "api/deposit-data", + "label": "Deposit Data" + }, + { + "type": "doc", + "id": "api/terms-and-conditions", + "label": "Terms And Conditions" + }, + { + "type": "doc", + "id": "api/techne-credentials", + "label": "Techne Credentials" + }, + { + "type": "doc", + "id": "api/address", + "label": "Address" + }, + { + "type": "doc", + "id": "api/owr-information", + "label": "OWR Information" + }, + { + "type": "doc", + "id": "api/test", + "label": "Test" + }, + { + "type": "doc", + "id": "api/tvs", + "label": "TVS" + }, + { + "type": "link", + "label": "Specification", + "href": "https://api.obol.tech/docs-json" + } + ] +} \ No newline at end of file diff --git a/versions.json b/versions.json index 79e06da804..effa00484e 100644 --- a/versions.json +++ b/versions.json @@ -1 +1,10 @@ -["v1.10"] +[ + "v1.10", + "v1.9", + "v1.8", + "v1.7", + "v1.6", + "v1.5", + "v1.4", + "v1.3" +] \ No newline at end of file