Skip to content

Commit

Permalink
chore: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Oct 22, 2024
1 parent 21b7b1d commit eb21c4b
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 128 deletions.
4 changes: 2 additions & 2 deletions bolt-cli/src/config.rs → bolt-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct Opts {

#[derive(Subcommand, Debug, Clone, Deserialize)]
pub enum Commands {
/// Generate delegation messages.
Generate {
/// Generate BLS delegation or revocation messages.
Delegate {
/// The BLS public key to which the delegation message should be signed.
#[clap(long, env = "DELEGATEE_PUBKEY")]
delegatee_pubkey: String,
Expand Down
110 changes: 101 additions & 9 deletions bolt-cli/src/delegation.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use alloy::signers::k256::sha2::{Digest, Sha256};
use ethereum_consensus::crypto::{
PublicKey as BlsPublicKey, SecretKey as BlsSecretKey, Signature as BlsSignature,
};
use eyre::Result;
use lighthouse_eth2_keystore::Keystore;
use serde::Serialize;

use crate::{
config::{Action, Chain},
types::{
DelegationMessage, RevocationMessage, SignedDelegation, SignedMessage, SignedRevocation,
},
cli::{Action, Chain},
utils::{
keystore::{keystore_paths, KeystoreError, KeystoreSecret},
signing::compute_commit_boost_signing_root,
Expand Down Expand Up @@ -100,17 +99,110 @@ pub fn generate_from_keystore(
Ok(signed_messages)
}

/// Event types that can be emitted by the validator pubkey to
/// signal some action on the Bolt protocol.
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
enum SignedMessageAction {
/// Signal delegation of a validator pubkey to a delegatee pubkey.
Delegation,
/// Signal revocation of a previously delegated pubkey.
Revocation,
}

/// Transparent serialization of signed messages.
/// This is used to serialize and deserialize signed messages
///
/// e.g. serde_json::to_string(&signed_message):
/// ```
/// {
/// "message": {
/// "action": 0,
/// "validator_pubkey": "0x...",
/// "delegatee_pubkey": "0x..."
/// },
/// "signature": "0x..."
/// },
/// ```
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum SignedMessage {
Delegation(SignedDelegation),
Revocation(SignedRevocation),
}

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct SignedDelegation {
pub message: DelegationMessage,
pub signature: BlsSignature,
}

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct DelegationMessage {
action: u8,
pub validator_pubkey: BlsPublicKey,
pub delegatee_pubkey: BlsPublicKey,
}

impl DelegationMessage {
/// Create a new delegation message.
pub fn new(validator_pubkey: BlsPublicKey, delegatee_pubkey: BlsPublicKey) -> Self {
Self { action: SignedMessageAction::Delegation as u8, validator_pubkey, delegatee_pubkey }
}

/// Compute the digest of the delegation message.
pub fn digest(&self) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update([self.action]);
hasher.update(self.validator_pubkey.to_vec());
hasher.update(self.delegatee_pubkey.to_vec());

hasher.finalize().into()
}
}

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct SignedRevocation {
pub message: RevocationMessage,
pub signature: BlsSignature,
}

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct RevocationMessage {
action: u8,
pub validator_pubkey: BlsPublicKey,
pub delegatee_pubkey: BlsPublicKey,
}

impl RevocationMessage {
/// Create a new revocation message.
pub fn new(validator_pubkey: BlsPublicKey, delegatee_pubkey: BlsPublicKey) -> Self {
Self { action: SignedMessageAction::Revocation as u8, validator_pubkey, delegatee_pubkey }
}

/// Compute the digest of the revocation message.
pub fn digest(&self) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update([self.action]);
hasher.update(self.validator_pubkey.to_vec());
hasher.update(self.delegatee_pubkey.to_vec());

hasher.finalize().into()
}
}

#[cfg(test)]
mod tests {
use ethereum_consensus::crypto::PublicKey as BlsPublicKey;

use crate::{
config::{Action, Chain},
types::SignedMessage,
utils::{keystore::KeystoreSecret, parse_public_key, signing::verify_commit_boost_root},
cli::{Action, Chain},
utils::{
keystore::KeystoreSecret, parse_bls_public_key, signing::verify_commit_boost_root,
},
};

use super::generate_from_keystore;
use super::{generate_from_keystore, SignedMessage};

#[test]
fn test_delegation_keystore_signer_lighthouse() -> eyre::Result<()> {
Expand All @@ -121,7 +213,7 @@ mod tests {
let keystore_secret = KeystoreSecret::from_directory(secrets_path)?;

let delegatee_pubkey = "0x83eeddfac5e60f8fe607ee8713efb8877c295ad9f8ca075f4d8f6f2ae241a30dd57f78f6f3863a9fe0d5b5db9d550b93";
let delegatee_pubkey = parse_public_key(delegatee_pubkey)?;
let delegatee_pubkey = parse_bls_public_key(delegatee_pubkey)?;
let chain = Chain::Mainnet;

let signed_delegations = generate_from_keystore(
Expand Down
26 changes: 7 additions & 19 deletions bolt-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
use std::{fs, path::PathBuf};

use clap::Parser;
use eyre::{bail, Result};
use serde::Serialize;

mod config;
use config::{Commands, KeySource, Opts};
mod cli;
use cli::{Commands, KeySource, Opts};

mod delegation;
use delegation::{generate_from_keystore, generate_from_local_keys};
use utils::{keystore::KeystoreSecret, parse_public_key};

mod types;

mod utils;
use utils::{keystore::KeystoreSecret, parse_bls_public_key, write_to_file};

fn main() -> Result<()> {
let _ = dotenvy::dotenv();

let cli = Opts::parse();

match cli.command {
Commands::Generate { delegatee_pubkey, out, chain, source, action } => match source {
Commands::Delegate { delegatee_pubkey, out, chain, source, action } => match source {
KeySource::Local { secret_keys } => {
let delegatee = parse_public_key(&delegatee_pubkey)?;
let delegatee = parse_bls_public_key(&delegatee_pubkey)?;
let messages = generate_from_local_keys(&secret_keys, delegatee, &chain, action)?;

write_to_file(&out, &messages)?;
Expand All @@ -35,10 +30,11 @@ fn main() -> Result<()> {
} else if let Some(password) = password {
KeystoreSecret::from_unique_password(password)
} else {
// This case is prevented upstream by clap's validation.
bail!("Either `password_path` or `password` must be provided")
};

let delegatee = parse_public_key(&delegatee_pubkey)?;
let delegatee = parse_bls_public_key(&delegatee_pubkey)?;
let messages = generate_from_keystore(&path, passwords, delegatee, chain, action)?;

write_to_file(&out, &messages)?;
Expand All @@ -48,11 +44,3 @@ fn main() -> Result<()> {
}
Ok(())
}

/// Write some serializable data to an output json file
fn write_to_file<T: Serialize>(out: &str, data: &T) -> Result<()> {
let out_path = PathBuf::from(out);
let out_file = fs::File::create(out_path)?;
serde_json::to_writer_pretty(out_file, data)?;
Ok(())
}
96 changes: 0 additions & 96 deletions bolt-cli/src/types.rs

This file was deleted.

13 changes: 12 additions & 1 deletion bolt-cli/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::{fs, path::PathBuf};

use ethereum_consensus::crypto::PublicKey as BlsPublicKey;
use eyre::{Context, Result};
use serde::Serialize;

/// Utilities and types for EIP-2335 keystore files.
pub mod keystore;
Expand All @@ -8,8 +11,16 @@ pub mod keystore;
pub mod signing;

/// Parse a BLS public key from a string
pub fn parse_public_key(delegatee_pubkey: &str) -> Result<BlsPublicKey> {
pub fn parse_bls_public_key(delegatee_pubkey: &str) -> Result<BlsPublicKey> {
let hex_pk = delegatee_pubkey.strip_prefix("0x").unwrap_or(delegatee_pubkey);
BlsPublicKey::try_from(hex::decode(hex_pk).wrap_err("Failed to hex-decode pubkey")?.as_slice())
.map_err(|e| eyre::eyre!("Failed to parse public key '{}': {}", hex_pk, e))
}

/// Write some serializable data to an output json file
pub fn write_to_file<T: Serialize>(out: &str, data: &T) -> Result<()> {
let out_path = PathBuf::from(out);
let out_file = fs::File::create(out_path)?;
serde_json::to_writer_pretty(out_file, data)?;
Ok(())
}
2 changes: 1 addition & 1 deletion bolt-cli/src/utils/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ethereum_consensus::{
};
use eyre::Result;

use crate::config::Chain;
use crate::cli::Chain;

/// The domain mask for the Commit Boost domain.
pub const COMMIT_BOOST_DOMAIN_MASK: [u8; 4] = [109, 109, 111, 67];
Expand Down

0 comments on commit eb21c4b

Please sign in to comment.