# Node Operators Guide

## Ditto operator checklist

* Docker: ensure docker is installed on your system. To download Docker, follow the instructions listed [here](https://docs.docker.com/engine/install/).
* Golang: required for installing EigenLayer CLI. To download Go, follow the instructions listed [here](https://linuxtldr.com/installing-go/).

## Preparation

This step provides commands to install Docker and Golang on Ubuntu Linux. If you already installed them or this installation method not applicable to you see the links above.

For installing docker run this commands in order:

1. Add Docker's official GPG key:

```bash
sudo apt-get update
```

```bash
sudo apt-get install ca-certificates curl
```

```bash
sudo install -m 0755 -d /etc/apt/keyrings
```

```bash
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
```

```bash
sudo chmod a+r /etc/apt/keyrings/docker.asc
```

2. Add the repository to Apt sources:

```bash
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
```

3. Install docker

```bash
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

4. Check docker installation

```bash
docker --version
```

For installing golang run following command in order:

1. Install go

```bash
sudo apt install golang
```

2. Ensure go installed correctly

```bash
go version
```

3. Configure PATH

```bash
echo 'export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN' >> $HOME/.profile \
source $HOME/.profile
```

## Creating EigenLayer operator

This sections repeats most important steps of this [EigenLayer documentation](https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation).

### Install EigenLayer CLI

1. Install EigenLayer CLI using go

```bash
go install github.com/Layr-Labs/eigenlayer-cli/cmd/eigenlayer@latest
```

2. Check EigenLayer CLI installation

```bash
eigenlayer --version
```

### Generate keys

Generate encrypted ECDSA and BLS keys using the CLI:

### Attention: SAVE PASSWORD FOR USE LATER

```bash
eigenlayer keys create --key-type ecdsa [keyname]
```

```bash
eigenlayer keys create --key-type bls [keyname]
```

* `[keyname]` — This will be the name of the created key file. It will be saved as `<keyname>.ecdsa.key.json` or `<keyname>.bls.key.json`

This will prompt a password which you can use to encrypt the keys. Keys will be stored in a local disk and will be shown once keys are created.

#### Output

```
Enter password to encrypt the ecdsa private key:
Please confirm your password:

Key location: /home/ubuntu/.eigenlayer/operator_keys/keyname.ecdsa.key.json
Public Key hex: 14495b007d8d7e8436cf0cfb7c653a91176cbb05cfbf3334b87be3019a824930bc2a0855971efd1f28508e5367f7de7fc1dea6203a2b8bc939e74b049653da72
Ethereum Address: 0xA5419b78F963778aC61FC3c5241d4f09d2275910
```

The `Ethereum Address` is the address of your operator.

You can add this wallet to metamask by `ECDSA Private Key`.

#### List existing keys

You can list existing keys using

```bash
eigenlayer keys list
```

#### View Private key (recovery)

You can view(recovery) ECDSA and BLS private keys using the CLI:

```bash
eigenlayer keys export --key-type ecdsa [keyname]
```

```bash
eigenlayer keys export --key-type bls [keyname]
```

### Fund ESDSA wallet

Send **at least 1 ETH** to the “address” field referenced in your operator.yaml file. This ETH will be used to cover the gas cost for operator registration in the subsequent steps.

If you are deploying to Testnet, please follow the instructions in [Obtaining Testnet ETH](https://docs.eigenlayer.xyz/restaking-guides/restaking-user-guide/testnet/obtaining-testnet-eth-and-liquid-staking-tokens-lsts) to fund a web3 wallet with HolEth.

### Create operator config

Run to create operator.yaml

```bash
eigenlayer operator config create
```

During creation you will be prompted to input those parameters

* Operator address — address you got from generating ecdsa key
* Earning address — can leave it empty, default to operator address. This address where you earning will be transferred to.
* ETH RPC url — RPC url of the node. More on that in [here](#rpc-nodes).
* Network — the network you want to create your operator on. More on this [here](#networks).
* Signer type — select `local_keystore`.

After completion you will have `operator.yaml` looking like this:

{% code title="operator.yaml" %}

```yaml
operator:
    address: <your_operator_address>
    earnings_receiver_address: <your_receiver_address>
    delegation_approver_address: "0x0000000000000000000000000000000000000000"
    staker_opt_out_window_blocks: 0
    metadata_url: ""
el_delegation_manager_address: 0xA44151489861Fe9e3055d95adC98FbD462B948e7
eth_rpc_url: <your_rpc_node_address>
chain_id: 17000
private_key_store_path: /root/.eigenlayer/operator_keys/op-ecdsa.ecdsa.key.json
signer_type: local_keystore
fireblocks:
    api_key: ""
    secret_key: ""
    base_url: ""
    vault_account_name: ""
    secret_storage_type: ""
    aws_region: ""
    timeout: 0
web3:
    url: ""
```

{% endcode %}

### Create metadata

#### Publish metadata to github

In order to register operator on EigenLayer you need to have a publicly accessible metadata file.

Best way to do so is creating Github repository.

In your github repository upload logo in png format and following manifest replacing placeholders with valid values:

```json
{
  "name": "<name_of_you_operator>",
  "website": "<your_website>",
  "description": "<description>",
  "logo": "https://raw.githubusercontent.com/<your_github_username>/<your_repository_name>/main/<name_of_the_logo_file>",
  "twitter": "<your_twitter_url>"
}
```

More on this [here](https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation#operator-configuration-and-registration).

#### Add reference to `operator.yaml`

Fill the `metadata_url` field in your `operator.yaml` file with the link to your `manifest.json`

```yaml
manifest_url: "https://raw.githubusercontent.com/<your_github_username>/<your_repository_name>/main/metadata.json"
```

### Register operator on EigenLayer

Run the following command to register your operator on EigenLayer:

```bash
eigenlayer operator register operator.yaml
```

You should get a link to your operator page on succesfull creation.

## Registering operator in Ditto AVS

### Pull Ditto Entry Point docker container

```bash
docker pull dittonetwork/avs-operator
```

### Add required ENV variables

Run this commands to add required ENV variables:

```bash
echo 'export OPERATOR_PRIVATE_KEY=<your_private_key>' >> $HOME/.profile
echo 'export EXECUTOR_PRIVATE_KEY=<your_signer_private_key>' >> $HOME/.profile \
source $HOME/.profile
```

In `EXECUTOR_PRIVATE_KEY` you can specify your wallet private key or generate new using this command:

```bash
docker run --rm dittonetwork/avs-operator generate
```

### Register on Ditto AVS

```bash
docker run --rm --env OPERATOR_PRIVATE_KEY dittonetwork/avs-operator register \
	--node-url <node_url> \
	--contract-addr <contract_addr>
```

* `node-url`— RPC url of the node. More on that in [here](#rpc-nodes).
* `contract-addr` — Specifies the address of the Ditto Entry Point contract. See [here](#ditto-entry-point-address).

### Set delegated signer

```bash
docker run --rm --env OPERATOR_PRIVATE_KEY dittonetwork/avs-operator set-signer \
	--node-url <node_url> \
	--contract-addr <contract_addr> \
	--address <delegated signer address 0x...>
```

* `node-url`— RPC url of the node. More on that in [here](#rpc-nodes).
* `contract-addr` — Specifies the address of the Ditto Entry Point contract. See [here](#ditto-entry-point-address).
* `address` — Address of executor, private key for which you provided in `EXECUTOR_PRIVATE_KEY`.

### Launch operator

Finally run docker container to start your operator:

You need some amount of ETH to start.

```bash
docker run --name ditto-operator --env EXECUTOR_PRIVATE_KEY --restart unless-stopped -d dittonetwork/avs-operator run \
	--node-url <node_url> \
	--contract-addr <contract_addr>
```

* `node-url`— RPC url of the node. More on that in [here](#rpc-nodes).
* `contract-addr` — Specifies the address of the Ditto Entry Point contract. See [here](#ditto-entry-point-address).

{% hint style="info" %}
You can read more on Ditto operator [here](https://ditto-network-1.gitbook.io/ditto-network-documentation/overview/protocol-design-avs).
{% endhint %}

### Monitor logs

To access operator logs run:

```bash
docker logs ditto-operator
```

Ensure there are no errors and operator started polling for updates (it can take some time for it to start).

## Deregistering operator in Ditto AVS

### Graceful shutdown and deactivation

On graceful shutdown operator will deactivate automaticly. However if you need to force deactivate use this command.

```bash
docker run --rm --env EXECUTOR_PRIVATE_KEY dittonetwork/avs-operator deactivate \
	--node-url <node_url> \
	--contract-addr <contract_addr>
```

* `node-url`— RPC url of the node. More on that in [here](#rpc-nodes).
* `contract-addr` — Specifies the address of the Ditto Entry Point contract. See [here](#ditto-entry-point-address).

{% hint style="info" %}
**ATTENTION!** Wait until rearrangement happens (epoch increment). You could attach to container logs. Firstly, you’ll observe *not executor* messages, then it will become either *Not my turn to execute* or info about active workflows in case if it is your turn. You’re now in a forever loop, being a part of the executors network. Congrats ^^
{% endhint %}

### Deregister operator

Run this command to deregister operator from Ditto AVS.

```bash
 docker run --rm --env OPERATOR_PRIVATE_KEY dittonetwork/avs-operator deregister \
	--node-url <node_url> \
	--contract-addr <contract_addr>
```

## Reference

### Networks

List of available networks with chainId.

* Mainnet - 1
* Holesky - 17000

Currently Ditto AVS supports only Holesky testnet.

### RPC nodes

Used to make contract calls, send transactions, and receive real-time updates via WebSocket connections. The node can be a local full node, a hosted node, or a service provider’s endpoint (e.g., [Infura](https://www.infura.io/), [Alchemy](https://www.alchemy.com/), [Quicknode](https://www.quicknode.com/)). Ensure that the node has the necessary access and permissions for your operations.

Example url: `wss://mainnet.infura.io/ws/v3/YOUR-PROJECT-ID`.

Example lists of RPC node providers:

* <https://www.alchemy.com/list-of/rpc-node-providers-on-ethereum>
* <https://chainlist.org/?search=&testnets=true>

### Ditto entry point address

List of addresses of the Ditto entry point.

Currently only holesky.

* Holesky — 0x5FD0026a449eeA51Bd1471E4ee8df8607aaECC24
