Skip to content

Commit

Permalink
Merge pull request #2274 from input-output-hk/sfa/2271/add_command_to…
Browse files Browse the repository at this point in the history
…_create_keypair

Add an `era` subcommand to create keypair
  • Loading branch information
sfauvel authored Feb 4, 2025
2 parents b4ad474 + 257cb8f commit b797355
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 5 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions docs/website/root/manual/develop/nodes/mithril-aggregator.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Usage: mithril-aggregator era <COMMAND>
Commands:
list Era list command
generate-tx-datum Era tx datum generate command
generate-keypair Era keypair generation command
help Print this message or the help of the given subcommand(s)

Options:
Expand Down Expand Up @@ -401,6 +402,7 @@ Here are the available subcommands:
| **genesis generate-keypair** | Generates a genesis keypair |
| **era list** | Lists the supported eras |
| **era generate-tx-datum** | Generates the era markers transaction datum to be stored on-chain |
| **era generate-keypair** | Generates an era keypair |
| **tools recompute-certificates-hash** | Loads all certificates in the database, recomputing their hash, and updating all related entities |

## Configuration parameters
Expand Down Expand Up @@ -506,4 +508,10 @@ Here is a list of the available parameters:
| `era_markers_secret_key` | `--era-markers-secret-key` | - | `ERA_MARKERS_SECRET_KEY` | Era markers secret key that is used to verify the authenticity of the era markers on the chain. | - | - | :heavy_check_mark: |
| `target_path` | `--target-path` | - | - | Path of the file to export the payload to. | - | - | - |

`era generate-keypair` command:

| Parameter | Command line (long) | Command line (short) | Environment variable | Description | Default value | Example | Mandatory |
| ------------- | ------------------- | :------------------: | -------------------- | ------------------------------------- | ------------- | ------- | :----------------: |
| `target_path` | `--target-path` | - | - | Target path for the generated keypair | - | - | :heavy_check_mark: |

The `tools recompute-certificates-hash` command has no dedicated parameters.
2 changes: 1 addition & 1 deletion mithril-aggregator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-aggregator"
version = "0.6.26"
version = "0.6.27"
description = "A Mithril Aggregator server"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
31 changes: 31 additions & 0 deletions mithril-aggregator/src/commands/era_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ pub enum EraSubCommand {

/// Era tx datum generate command.
GenerateTxDatum(GenerateTxDatumEraSubCommand),

/// Era keypair generation command.
GenerateKeypair(GenerateKeypairEraSubCommand),
}

impl EraSubCommand {
Expand All @@ -51,6 +54,7 @@ impl EraSubCommand {
match self {
Self::List(cmd) => cmd.execute(root_logger, config_builder).await,
Self::GenerateTxDatum(cmd) => cmd.execute(root_logger, config_builder).await,
Self::GenerateKeypair(cmd) => cmd.execute(root_logger, config_builder).await,
}
}
}
Expand Down Expand Up @@ -129,3 +133,30 @@ impl GenerateTxDatumEraSubCommand {
Ok(())
}
}

/// Era keypair generation command.
#[derive(Parser, Debug, Clone)]
pub struct GenerateKeypairEraSubCommand {
/// Target path for the generated keypair
#[clap(long)]
target_path: PathBuf,
}

impl GenerateKeypairEraSubCommand {
pub async fn execute(
&self,
root_logger: Logger,
_config_builder: ConfigBuilder<DefaultState>,
) -> StdResult<()> {
debug!(root_logger, "GENERATE KEYPAIR ERA command");
println!(
"Era generate keypair to {}",
self.target_path.to_string_lossy()
);

EraTools::create_and_save_era_keypair(&self.target_path)
.with_context(|| "era-tools: keypair generation error")?;

Ok(())
}
}
48 changes: 48 additions & 0 deletions mithril-aggregator/src/tools/era.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::{Path, PathBuf};

use anyhow::anyhow;
use mithril_common::{
chain_observer::{TxDatumBuilder, TxDatumFieldValue},
Expand Down Expand Up @@ -56,16 +58,41 @@ impl EraTools {
.build()?;
Ok(tx_datum.0)
}

/// Export the era keypair to a folder and returns the paths to the files (secret key, verification_key)
pub fn create_and_save_era_keypair(keypair_path: &Path) -> StdResult<(PathBuf, PathBuf)> {
let era_signer = EraMarkersSigner::create_non_deterministic_signer();
let era_secret_key_path = keypair_path.join("era.sk");
era_signer
.secret_key()
.write_json_hex_to_file(&era_secret_key_path)?;
let era_verification_key_path = keypair_path.join("era.vk");
era_signer
.verification_key()
.write_json_hex_to_file(&era_verification_key_path)?;

Ok((era_secret_key_path, era_verification_key_path))
}
}

#[cfg(test)]
mod tests {
use mithril_common::{
crypto_helper::{EraMarkersVerifierSecretKey, EraMarkersVerifierVerificationKey},
test_utils::TempDir,
};
use std::fs::read_to_string;

use super::*;

fn build_tools() -> EraTools {
EraTools {}
}

fn get_temp_dir(dir_name: &str) -> PathBuf {
TempDir::create("era", dir_name)
}

#[test]
fn get_supported_eras_list() {
let era_tools = build_tools();
Expand All @@ -92,4 +119,25 @@ mod tests {
.generate_tx_datum(Epoch(3), Some(Epoch(2)), &era_markers_signer)
.expect_err("generate_tx_datum should have failed");
}

#[test]
fn test_create_and_save_era_keypair() {
let temp_dir = get_temp_dir("test_create_and_save_era_keypair");
let (era_secret_key_path, era_verification_key_path) =
EraTools::create_and_save_era_keypair(&temp_dir)
.expect("Failed to create and save era keypair");
let era_secret_key = EraMarkersVerifierSecretKey::from_json_hex(
&read_to_string(&era_secret_key_path).expect("Failed to read era secret key file"),
)
.expect("Failed to parse era secret key");
let era_verification_key = EraMarkersVerifierVerificationKey::from_json_hex(
&read_to_string(&era_verification_key_path)
.expect("Failed to read era verification key file"),
)
.expect("Failed to parse era verification key");
let era_verifier = EraMarkersSigner::from_secret_key(era_secret_key).create_verifier();

let expected_era_verification_key = era_verifier.to_verification_key();
assert_eq!(expected_era_verification_key, era_verification_key);
}
}
2 changes: 1 addition & 1 deletion mithril-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-common"
version = "0.4.112"
version = "0.4.113"
description = "Common types, interfaces, and utilities for Mithril nodes."
authors = { workspace = true }
edition = { workspace = true }
Expand Down
11 changes: 10 additions & 1 deletion mithril-common/src/crypto_helper/era.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,22 @@ impl EraMarkersSigner {
Self::create_test_signer(rng)
}

#[cfg(test)]
/// [EraMarkersSigner] non deterministic
pub fn create_non_deterministic_signer() -> Self {
let rng = rand_core::OsRng;
Self::create_test_signer(rng)
}

/// Get the [EraMarkersVerifierSecretKey]
pub fn secret_key(&self) -> EraMarkersVerifierSecretKey {
self.secret_key.clone()
}

/// Get the [EraMarkersVerifierVerificationKey]
pub fn verification_key(&self) -> EraMarkersVerifierVerificationKey {
self.secret_key.verifying_key().into()
}

/// [EraMarkersSigner] from [EraMarkersVerifierSecretKey]
pub fn from_secret_key(secret_key: EraMarkersVerifierSecretKey) -> Self {
Self { secret_key }
Expand Down

0 comments on commit b797355

Please sign in to comment.