reth_cli_util/
load_secret_key.rs

1use reth_fs_util::{self as fs, FsPathError};
2use secp256k1::{Error as SecretKeyBaseError, SecretKey};
3use std::{
4    io,
5    path::{Path, PathBuf},
6};
7use thiserror::Error;
8
9/// Convenience function to create a new random [`SecretKey`]
10pub fn rng_secret_key() -> SecretKey {
11    SecretKey::new(&mut rand::thread_rng())
12}
13
14/// Errors returned by loading a [`SecretKey`], including IO errors.
15#[derive(Error, Debug)]
16pub enum SecretKeyError {
17    /// Error encountered during decoding of the secret key.
18    #[error(transparent)]
19    SecretKeyDecodeError(#[from] SecretKeyBaseError),
20
21    /// Error related to file system path operations.
22    #[error(transparent)]
23    SecretKeyFsPathError(#[from] FsPathError),
24
25    /// Represents an error when failed to access the key file.
26    #[error("failed to access key file {secret_file:?}: {error}")]
27    FailedToAccessKeyFile {
28        /// The encountered IO error.
29        error: io::Error,
30        /// Path to the secret key file.
31        secret_file: PathBuf,
32    },
33}
34
35/// Attempts to load a [`SecretKey`] from a specified path. If no file exists there, then it
36/// generates a secret key and stores it in the provided path. I/O errors might occur during write
37/// operations in the form of a [`SecretKeyError`]
38pub fn get_secret_key(secret_key_path: &Path) -> Result<SecretKey, SecretKeyError> {
39    let exists = secret_key_path.try_exists();
40
41    match exists {
42        Ok(true) => {
43            let contents = fs::read_to_string(secret_key_path)?;
44            Ok(contents.as_str().parse().map_err(SecretKeyError::SecretKeyDecodeError)?)
45        }
46        Ok(false) => {
47            if let Some(dir) = secret_key_path.parent() {
48                // Create parent directory
49                fs::create_dir_all(dir)?;
50            }
51
52            let secret = rng_secret_key();
53            let hex = alloy_primitives::hex::encode(secret.as_ref());
54            fs::write(secret_key_path, hex)?;
55            Ok(secret)
56        }
57        Err(error) => Err(SecretKeyError::FailedToAccessKeyFile {
58            error,
59            secret_file: secret_key_path.to_path_buf(),
60        }),
61    }
62}