Skip to content

Commit

Permalink
feat: working dirk delegation
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Oct 24, 2024
1 parent abeb889 commit 25eabbf
Show file tree
Hide file tree
Showing 13 changed files with 1,176 additions and 100 deletions.
7 changes: 0 additions & 7 deletions bolt-cli/.env.keystore.example

This file was deleted.

6 changes: 0 additions & 6 deletions bolt-cli/.env.local.example

This file was deleted.

5 changes: 3 additions & 2 deletions bolt-cli/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/target

.env
.env.*

delegations.json
!.env.local.example
!.env.keystore.example
pubkeys.json
231 changes: 179 additions & 52 deletions bolt-cli/README.md
Original file line number Diff line number Diff line change
@@ -1,82 +1,209 @@
# Bolt CLI

Components:
The Bolt CLI is a collection of command-line tools for interacting with the Bolt protocol.

- `bolt-delegations-cli`: A command-line tool for generating delegation messages signed with a BLS12-381 key.
## Installation

## Bolt-delegations-cli
The Bolt CLI can be built with Cargo. If you don't have the Rust toolchain installed
on your machine, you can follow the steps [here](https://www.rust-lang.org/tools/install).

`bolt-delegations-cli` is an offline command-line tool for safely generating delegation messages
signed with a BLS12-381 key for the [Constraints API](https://docs.boltprotocol.xyz/api/builder)
in [Bolt](https://docs.boltprotocol.xyz/).
Once you have Rust installed, you can build the CLI binary in the following way:

The tool supports two key sources:
```shell
# clone the Bolt repository if you haven't already
git clone [email protected]:chainbound/bolt.git

- Local: A BLS private key provided directly from a file.
- Keystore: A keystore file that contains an encrypted BLS private key.
# navigate to the Bolt CLI package directory
cd bolt-cli

Features:
# build and install the binary on your machine
cargo install --path . --force

- Offline usage: Safely generate delegation messages in an offline environment.
- Flexible key source: Support for both direct local BLS private keys and Ethereum keystore files (ERC-2335 format).
- BLS delegation signing: Sign delegation messages using a BLS secret key and output the signed delegation in JSON format.
# test the installation
bolt-cli --version
```

## Usage

Available commands:

- [`delegate`](#delegate) - Generate BLS delegation messages for the Constraints API.
- [`pubkeys`](#pubkeys) - List available BLS public keys from various key sources.

### `Delegate`

The `delegate` command generates signed delegation messages for the Constraints API.
To learn more about the Constraints API, please refer to the [Bolt documentation][bolt-docs].

The command supports three key sources for generating the signed messages:

- Local BLS secret keys (as hex-encoded strings) via `secret-keys`
- Local EIP-2335 filesystem keystore directories via `local-keystore`
- Remote Dirk keystore via `dirk` (requires TLS credentials)

<details>
<summary>Usage</summary>

```text
❯ bolt-cli delegate --help
Generate BLS delegation or revocation messages
Usage: bolt-cli delegate [OPTIONS] --delegatee-pubkey <DELEGATEE_PUBKEY> <COMMAND>
Commands:
secret-keys Use local secret keys to generate the signed messages
local-keystore Use an EIP-2335 filesystem keystore directory to generate the signed messages
dirk Use a remote DIRK keystore to generate the signed messages
help Print this message or the help of the given subcommand(s)
Options:
--delegatee-pubkey <DELEGATEE_PUBKEY>
The BLS public key to which the delegation message should be signed
[env: DELEGATEE_PUBKEY=]
--out <OUT>
The output file for the delegations
[env: OUTPUT_FILE_PATH=]
[default: delegations.json]
--chain <CHAIN>
The chain for which the delegation message is intended
[env: CHAIN=]
[default: mainnet]
[possible values: mainnet, holesky, helder, kurtosis]
--action <ACTION>
The action to perform. The tool can be used to generate delegation or revocation messages (default: delegate)
[env: ACTION=]
[default: delegate]
Possible values:
- delegate: Create a delegation message
- revoke: Create a revocation message
-h, --help
Print help (see a summary with '-h')
```

</details>

### Usage
<details>
<summary>Examples</summary>

1. Generating a delegation using a local BLS secret key

```text
bolt-cli delegate \
--delegatee-pubkey 0x8d0edf4fe9c80cd640220ca7a68a48efcbc56a13536d6b274bf3719befaffa13688ebee9f37414b3dddc8c7e77233ce8 \
--chain holesky \
secret-keys --secret-keys 642e0d33fde8968a48b5f560c1b20143eb82036c1aa6c7f4adc4beed919a22e3
```

2. Generating a delegation using an ERC-2335 keystore directory

```text
bolt-cli delegate \
--delegatee-pubkey 0x8d0edf4fe9c80cd640220ca7a68a48efcbc56a13536d6b274bf3719befaffa13688ebee9f37414b3dddc8c7e77233ce8 \
--chain holesky \
local-keystore --path test_data/lighthouse/validators --password-path test_data/lighthouse/secrets
```

3. Generating a revocation using a remote DIRK keystore

```text
bolt-cli delegate \
--delegatee-pubkey 0x83eeddfac5e60f8fe607ee8713efb8877c295ad9f8ca075f4d8f6f2ae241a30dd57f78f6f3863a9fe0d5b5db9d550b93 \
dirk --url https://localhost:9091 \
--client-cert-path ./test_data/dirk/client1.crt \
--client-key-path ./test_data/dirk/client1.key \
--ca-cert-path ./test_data/dirk/security/ca.crt \
--wallet-path wallet1 --passphrases secret
```

</details>

### `Pubkeys`

The `pubkeys` command lists available BLS public keys from different key sources:

- Local BLS secret keys (as hex-encoded strings) via `secret-keys`
- Local EIP-2335 filesystem keystore directories via `local-keystore`
- Remote Dirk keystore via `dirk` (requires TLS credentials)

<details>
<summary>Usage</summary>

```text
A CLI tool to generate signed delegation messages for BLS keys
❯ bolt-cli pubkeys --help
Output a list of pubkeys in JSON format
Usage: bolt-delegations-cli <COMMAND>
Usage: bolt-cli pubkeys [OPTIONS] <COMMAND>
Commands:
generate Generate delegation messages
help Print this message or the help of the given subcommand(s)
secret-keys Use local secret keys to generate the signed messages
local-keystore Use an EIP-2335 filesystem keystore directory to generate the signed messages
dirk Use a remote DIRK keystore to generate the signed messages
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
--out <OUT> The output file for the pubkeys [env: OUTPUT_FILE_PATH=] [default: pubkeys.json]
-h, --help Print help
```

</details>

<details>
<summary>Examples</summary>

1. Listing BLS public keys from a local secret key

```text
bolt-cli pubkeys secret-keys --secret-keys 642e0d33fde8968a48b5f560c1b20143eb82036c1aa6c7f4adc4beed919a22e3
```

#### Example
2. Listing BLS public keys from an ERC-2335 keystore directory

1. Using a local BLS private key:
```text
bolt-cli pubkeys local-keystore \
--path test_data/lighthouse/validators \
--password-path test_data/lighthouse/secrets
```

```text
bolt-delegations-cli generate \
--delegatee-pubkey 0x7890ab... \
--out my_delegations.json \
--chain kurtosis \
local \
--secret-keys 0xabc123...,0xdef456..
```
3. Listing BLS public keys from a remote DIRK keystore

2. Using an Ethereum keystore file:
```text
bolt-cli pubkeys dirk --url https://localhost:9091 \
--client-cert-path ./test_data/dirk/client1.crt \
--client-key-path ./test_data/dirk/client1.key \
--ca-cert-path ./test_data/dirk/security/ca.crt \
--wallet-path wallet1 --passphrases secret
```

```text
bolt-delegations-cli generate \
--delegatee-pubkey 0x7890ab... \
--out my_delegations.json \
--chain kurtosis \
keystore \
--path /keys \
--password myS3cr3tP@ssw0rd
```
</details>

When using the `keystore` key source, the `--path` flag should point to the directory
containing the encrypted keypair directories.
---

In case of validator-specific passwords (e.g. Lighthouse format) the `--password-path`
flag must be used instead of `--password`, pointing to the directory containing the password files.
## Security

You can find a reference Lighthouse keystore [here](./test_data/lighthouse/).
The Bolt CLI is designed to be used offline. It does not require any network connections
unless you are using the remote `dirk` key source. In that case, the tool will connect to
the Dirk server with the provided TLS credentials.

#### Supported Chains
The tool does not store any sensitive information beyond the duration of the execution.
It is recommended to use the tool in a secure environment and to avoid storing any sensitive
information in the shell history.

The tool supports the following chains:
If you have any security concerns or have found a security issue/bug, please contact Chainbound
on our official [Discord][discord] or [Twitter][twitter] channels.

- `mainnet`
- `holesky`
- `helder`
- `kurtosis`
<!-- Links -->

Each chain has its specific fork version used in computing the signing root.
[bolt-docs]: https://docs.boltprotocol.xyz/
[discord]: https://discord.gg/G5BJjCD9ss
[twitter]: https://twitter.com/chainbound_
7 changes: 6 additions & 1 deletion bolt-cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ fn main() -> io::Result<()> {
}

tonic_build::configure().build_client(true).out_dir(PB_OUT_DIR).compile_protos(
&["proto/eth2-signer-api/v1/lister.proto", "proto/eth2-signer-api/v1/signer.proto"],
&[
"proto/eth2-signer-api/v1/lister.proto",
"proto/eth2-signer-api/v1/signer.proto",
"proto/eth2-signer-api/v1/accountmanager.proto",
"proto/eth2-signer-api/v1/walletmanager.proto",
],
&["proto/eth2-signer-api/v1/", "proto/eth2-signer-api/"],
)
}
15 changes: 10 additions & 5 deletions bolt-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::Deserialize;

use crate::utils::keystore::DEFAULT_KEYSTORE_PASSWORD;

/// A CLI tool to generate signed delegation messages for BLS keys.
/// A CLI tool to interact with Bolt Protocol ✨
#[derive(Parser, Debug, Clone, Deserialize)]
#[command(author, version, about, long_about = None)]
pub struct Opts {
Expand Down Expand Up @@ -119,13 +119,18 @@ pub struct DirkOpts {
#[clap(long, env = "DIRK_URL")]
pub url: String,

/// The path of the wallets in the DIRK keystore.
#[clap(long, env = "DIRK_WALLET_PATH")]
pub wallet_path: String,

/// The passphrases to unlock the wallet in the DIRK keystore.
/// If multiple are provided, they are tried in order until one works.
#[clap(long, env = "DIRK_PASSPHRASES", value_delimiter = ',', hide_env_values = true)]
pub passphrases: Option<Vec<String>>,

/// The TLS credentials for connecting to the DIRK keystore.
#[clap(flatten)]
pub tls_credentials: TlsCredentials,

/// The paths to the accounts in the DIRK keystore.
#[clap(long, env = "DIRK_ACCOUNTS", value_delimiter = ',', hide_env_values = true)]
pub accounts: Vec<String>,
}

/// TLS credentials for connecting to a remote server.
Expand Down
Loading

0 comments on commit 25eabbf

Please sign in to comment.