newton-core 0.4.16

newton protocol core sdk
//! Storage utilities for key files

use directories::ProjectDirs;
use std::{fs, path::PathBuf};
use tracing::info;

use crate::keys::error::{KeyError, KeyResult};

/// Get the base directory for storing keys
pub fn get_keys_directory() -> KeyResult<PathBuf> {
    let project_dirs = ProjectDirs::from("", "", "newton-prover-avs").ok_or_else(|| {
        KeyError::DirectoryCreation(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            "Could not determine data directory",
        ))
    })?;

    let keys_dir = project_dirs.data_dir().join("keys");
    info!("Keys directory: {}", keys_dir.display());
    Ok(keys_dir)
}

/// Ensure the keys directory exists
pub fn ensure_keys_directory() -> KeyResult<PathBuf> {
    let keys_dir = get_keys_directory()?;

    if !keys_dir.exists() {
        info!("Creating keys directory: {}", keys_dir.display());
        fs::create_dir_all(&keys_dir).map_err(KeyError::DirectoryCreation)?;

        // Set restrictive permissions on the directory (Unix only)
        #[cfg(unix)]
        {
            use std::os::unix::fs::PermissionsExt;
            let perms = fs::Permissions::from_mode(0o700);
            fs::set_permissions(&keys_dir, perms).map_err(KeyError::FileOperation)?;
        }
    }

    Ok(keys_dir)
}

/// Get the file path for an ECDSA key
pub fn get_ecdsa_key_path(name: &str) -> KeyResult<PathBuf> {
    let keys_dir = get_keys_directory()?;
    Ok(keys_dir.join(format!("{}-ecdsa.hex", name)))
}

/// Get the file path for a BLS key
pub fn get_bls_key_path(name: &str) -> KeyResult<PathBuf> {
    let keys_dir = get_keys_directory()?;
    Ok(keys_dir.join(format!("{}-bls.hex", name)))
}

/// Write a hex-encoded private key to a file
pub fn write_key_file(path: &PathBuf, hex_key: &str) -> KeyResult<()> {
    ensure_keys_directory()?;

    info!("Writing key to: {}", path.display());
    fs::write(path, hex_key).map_err(KeyError::FileOperation)?;

    // Set restrictive permissions on the file (Unix only)
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let perms = fs::Permissions::from_mode(0o600);
        fs::set_permissions(path, perms).map_err(KeyError::FileOperation)?;
    }

    info!("Key saved to: {}", path.display());
    Ok(())
}

/// Read a hex-encoded private key from a file
pub fn read_key_file(path: &PathBuf) -> KeyResult<String> {
    if !path.exists() {
        return Err(KeyError::KeyNotFound(path.display().to_string()));
    }

    info!("Reading key from: {}", path.display());
    let content = fs::read_to_string(path).map_err(KeyError::FileOperation)?;

    // trim whitespace from the key content
    Ok(content.trim().to_string())
}