Skip to content

Commit

Permalink
Fix prater withdrawal credentials (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsudmi authored Dec 7, 2021
1 parent 8e9e562 commit 5e6ab03
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 27 deletions.
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Operator CLI

Operators CLI is responsible for generating the validators keys,
deposit data required to register them and uploading the keys to the Hashicorp Vault.
Operators CLI generates validators keys and deposit data for the validators.
The validator keys have to be uploaded to the Hashicorp Vault for the secure storage.
Read more about operators onboarding process [here](https://docs.stakewise.io/node-operator/dao-proposal)

## Usage

Expand All @@ -11,7 +12,7 @@ See [releases page](https://github.com/stakewise/cli/releases) to download and d

### Step 2. Generate DAO proposal

Run the following command to generate DAO proposal:
Run the following command to generate the DAO proposal specification:

```bash
./operator-cli generate-proposal
Expand All @@ -23,45 +24,46 @@ It will allow you to restore the keys in case the Vault will get corrupted or lo
### Step 3. Submit DAO proposal

Create a post about joining operators set at [StakeWise Forum](https://vote.stakewise.io).
In your post you must include the `Specification` section that was generated in step 2.
In your post you must include the `Specification` section that was generated in the previous step.

### Step 4. Deploy ETH2 infrastructure

If the proposal from step 3 is approved by the DAO, follow the instructions [here](https://github.com/stakewise/helm-charts/tree/main/charts/operator#readme)
If the proposal from the previous step got approved by the DAO, follow the instructions [here](https://docs.stakewise.io/node-operator/infrastructure)
to deploy the ETH2 staking infrastructure.

### Step 5. Sync keys to the Vault

You must **use the same mnemonic** as generated in step 1.
Also, **using the same mnemonic for multiple vaults will result into validator slashing**.
Also, **using the same mnemonic for multiple vaults will result into validators slashings**.

Run the following command to sync new validator keys to the vault:

```bash
./operator-cli sync-vault
```

After uploading the keys, restart the validators that got new keys added.
After uploading the keys, make sure you have the right number of validators running and restart those that got new keys added.

### Step 6. Commit Operator

Once you're 100% ready for ether assignments to the validators, commit your operator:
Once you're 100% ready for Ether assignments, commit your operator:

- Go to the [Operators smart contract](https://etherscan.io/address/<address>#writeProxyContract)
- Go to the Operators smart contract ([Goerli](https://goerli.etherscan.io/address/0x0d92156861a0BC7037cC21470327Bd3Bc750EB1D#writeProxyContract), Mainnet)
- Click on `Connect to Web3` button and connect your wallet. The address must match the one used during proposal generation.
- Call `commitOperator` function. If that's your onboarding, you must deposit 1 ETH collateral together with the call.
- Call `commitOperator` function. If that's your onboarding, you must deposit 1 ETH (specified in Wei) collateral together with the call.

Congratulations on becoming StakeWise Node Operator🎉.
Your validators will get ether assigned, and you can claim your operator rewards from [Farms Page](https://app.stakewise.io/farms).


### Operator CLI Environment Settings

| Variable | Description | Required | Default |
|------------------------------|---------------------------------------------------------------------|----------|-------------------------------------------------------------------------|
| WITHDRAWAL_CREDENTIALS | The withdrawal credentials of the validators used in deposit data | No | 0x0100000000000000000000002296e122c1a20fca3cac3371357bdad3be0df079 |
| IPFS_PIN_ENDPOINTS | The IPFS endpoint where the deposit data will be uploaded | No | /dns/ipfs.infura.io/tcp/5001/https |
| IPFS_FETCH_ENDPOINTS | The IPFS endpoints from where the deposit data will be fetched | No | https://gateway.pinata.cloud,http://cloudflare-ipfs.com,https://ipfs.io |
| IPFS_PINATA_API_KEY | The Pinata API key for uploading deposit data for the redundancy | No | - |
| IPFS_PINATA_SECRET_KEY | The Pinata Secret key for uploading deposit data for the redundancy | No | - |
| VAULT_VALIDATORS_MOUNT_POINT | The mount point in Hashicorp Vault for storing validator keys | No | validators |
| Variable | Description | Required | Default |
|--------------------------------|----------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------|
| MAINNET_WITHDRAWAL_CREDENTIALS | The withdrawal credentials of the validators used in mainnet deposit data | No | 0x0100000000000000000000002296e122c1a20fca3cac3371357bdad3be0df079 |
| PRATER_WITHDRAWAL_CREDENTIALS | The withdrawal credentials of the validators used in prater testnet deposit data | No | 0x003e294ffc37978496f1b9298d5984ad4d55d4e2d1e6a06ee6904810c7b9e0d5 |
| IPFS_PIN_ENDPOINTS | The IPFS endpoint where the deposit data will be uploaded | No | /dns/ipfs.infura.io/tcp/5001/https |
| IPFS_FETCH_ENDPOINTS | The IPFS endpoints from where the deposit data will be fetched | No | https://gateway.pinata.cloud,http://cloudflare-ipfs.com,https://ipfs.io |
| IPFS_PINATA_API_KEY | The Pinata API key for uploading deposit data for the redundancy | No | - |
| IPFS_PINATA_SECRET_KEY | The Pinata Secret key for uploading deposit data for the redundancy | No | - |
| VAULT_VALIDATORS_MOUNT_POINT | The mount point in Hashicorp Vault for storing validator keys | No | validators |
5 changes: 4 additions & 1 deletion operator_cli/commands/generate_proposal.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,15 @@ def generate_proposal(chain: str, existing_vault: bool) -> None:
default=50.00,
value_proc=validate_share_percentage,
)
specification += f"""
if share_percentage > 0:
specification += f"""
- DAO calls `setOperator` function of `Roles` contract with the following parameters:
* account: `{operator}`
* revenueShare: `{share_percentage}`
"""

specification += """
- If the proposal will be approved, the operator must perform the following steps:
* Call `operator-cli sync-vault` with the same mnemonic as used for the proposal
Expand Down
5 changes: 5 additions & 0 deletions operator_cli/commands/sync_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,8 @@ def sync_vault(chain: str) -> None:

vault.apply_vault_changes()
vault.verify_vault_keystores()
click.echo(
f"Make sure you have the following validators"
f" running in the {namespace} namespace: {','.join(sorted(vault.vault_validator_names))}."
f" Restart them if they were updated."
)
24 changes: 18 additions & 6 deletions operator_cli/eth2.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
derive_child_SK,
derive_master_SK,
)
from eth2deposit.settings import BaseChainSetting
from eth2deposit.settings import PRATER, BaseChainSetting
from eth2deposit.utils.ssz import DepositData as SSZDepositData
from eth2deposit.utils.ssz import (
DepositMessage,
Expand All @@ -33,7 +33,11 @@

from operator_cli.merkle_tree import MerkleTree
from operator_cli.queries import REGISTRATIONS_QUERY
from operator_cli.settings import MIGRATE_LEGACY, WITHDRAWAL_CREDENTIALS
from operator_cli.settings import (
MAINNET_WITHDRAWAL_CREDENTIALS,
MIGRATE_LEGACY,
PRATER_WITHDRAWAL_CREDENTIALS,
)
from operator_cli.typings import (
BLSPrivkey,
Bytes4,
Expand Down Expand Up @@ -237,9 +241,17 @@ def generate_merkle_deposit_datum(
validator_keypairs: List[KeyPair],
) -> Tuple[HexStr, List[MerkleDepositData]]:
"""Generates deposit data with merkle proofs for the validators."""
withdrawal_credentials_bytes: Bytes32 = Bytes32(
w3.toBytes(hexstr=WITHDRAWAL_CREDENTIALS)
)
if chain_setting.ETH2_NETWORK_NAME == PRATER:
withdrawal_credentials: HexStr = PRATER_WITHDRAWAL_CREDENTIALS
withdrawal_credentials_bytes: Bytes32 = Bytes32(
w3.toBytes(hexstr=PRATER_WITHDRAWAL_CREDENTIALS)
)
else:
withdrawal_credentials: HexStr = MAINNET_WITHDRAWAL_CREDENTIALS
withdrawal_credentials_bytes: Bytes32 = Bytes32(
w3.toBytes(hexstr=MAINNET_WITHDRAWAL_CREDENTIALS)
)

deposit_amount_gwei: Gwei = Gwei(int(w3.fromWei(deposit_amount, "gwei")))
merkle_deposit_datum: List[MerkleDepositData] = []
merkle_elements: List[bytes] = []
Expand Down Expand Up @@ -270,7 +282,7 @@ def generate_merkle_deposit_datum(
public_key=public_key,
signature=w3.toHex(signature),
amount=str(deposit_amount),
withdrawal_credentials=WITHDRAWAL_CREDENTIALS,
withdrawal_credentials=withdrawal_credentials,
deposit_data_root=w3.toHex(deposit_data_root),
proof=[],
)
Expand Down
8 changes: 6 additions & 2 deletions operator_cli/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
PRATER: PraterSetting,
}

WITHDRAWAL_CREDENTIALS = config(
"WITHDRAWAL_CREDENTIALS",
MAINNET_WITHDRAWAL_CREDENTIALS = config(
"MAINNET_WITHDRAWAL_CREDENTIALS",
default="0x0100000000000000000000002296e122c1a20fca3cac3371357bdad3be0df079",
)
PRATER_WITHDRAWAL_CREDENTIALS = config(
"PRATER_WITHDRAWAL_CREDENTIALS",
default="0x003e294ffc37978496f1b9298d5984ad4d55d4e2d1e6a06ee6904810c7b9e0d5",
)

# extra pins to pinata for redundancy
IPFS_PIN_ENDPOINTS = config(
Expand Down
7 changes: 7 additions & 0 deletions operator_cli/vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,13 @@ def sync_vault_keystores(self) -> None:
)

def verify_vault_keystores(self) -> None:
# clean up cached property
try:
# noinspection PyPropertyAccess
del self.vault_validator_names
except AttributeError:
pass

public_keys: Set[BLSPubkey] = set()
with click.progressbar(
self.vault_validator_names,
Expand Down

0 comments on commit 5e6ab03

Please sign in to comment.