From 89315f0c2aea4b16f6f2a2b08e31a243b308392f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 5 Jan 2024 14:10:41 +0000 Subject: [PATCH] cleaned up key loading --- nym-api/src/coconut/dkg/client.rs | 1 - nym-api/src/coconut/dkg/controller/keys.rs | 45 ++++++++++++++ .../dkg/{controller.rs => controller/mod.rs} | 61 +++++++------------ nym-api/src/main.rs | 19 ++++-- nym-api/src/support/config/helpers.rs | 11 +++- 5 files changed, 88 insertions(+), 49 deletions(-) create mode 100644 nym-api/src/coconut/dkg/controller/keys.rs rename nym-api/src/coconut/dkg/{controller.rs => controller/mod.rs} (79%) diff --git a/nym-api/src/coconut/dkg/client.rs b/nym-api/src/coconut/dkg/client.rs index 630b7976fa..5691de1393 100644 --- a/nym-api/src/coconut/dkg/client.rs +++ b/nym-api/src/coconut/dkg/client.rs @@ -16,7 +16,6 @@ use nym_dkg::Threshold; use nym_validator_client::nyxd::cosmwasm_client::logs::{find_attribute, NODE_INDEX}; use nym_validator_client::nyxd::cosmwasm_client::types::ExecuteResult; use nym_validator_client::nyxd::AccountId; -use std::time::Duration; pub(crate) struct DkgClient { inner: Box, diff --git a/nym-api/src/coconut/dkg/controller/keys.rs b/nym-api/src/coconut/dkg/controller/keys.rs new file mode 100644 index 0000000000..f1528d305c --- /dev/null +++ b/nym-api/src/coconut/dkg/controller/keys.rs @@ -0,0 +1,45 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::support::config; +use anyhow::Context; +use nym_dkg::bte::keys::KeyPair as DkgKeyPair; +use rand::{CryptoRng, RngCore}; + +pub(crate) fn init_bte_keypair( + rng: &mut R, + config: &config::CoconutSigner, +) -> anyhow::Result<()> { + let dkg_params = nym_dkg::bte::setup(); + let kp = DkgKeyPair::new(&dkg_params, rng); + nym_pemstore::store_keypair( + &kp, + &nym_pemstore::KeyPairPath::new( + &config.storage_paths.decryption_key_path, + &config.storage_paths.public_key_with_proof_path, + ), + )?; + Ok(()) +} + +pub(crate) fn load_bte_keypair(config: &config::CoconutSigner) -> anyhow::Result { + nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( + &config.storage_paths.decryption_key_path, + &config.storage_paths.public_key_with_proof_path, + )) + .context("bte keypair load failure") +} + +pub(crate) fn load_coconut_keypair_if_exists( + config: &config::CoconutSigner, +) -> anyhow::Result> { + if !config.storage_paths.secret_key_path.exists() { + return Ok(None); + } + nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( + &config.storage_paths.secret_key_path, + &config.storage_paths.verification_key_path, + )) + .context("coconut keypair load failure") + .map(Some) +} diff --git a/nym-api/src/coconut/dkg/controller.rs b/nym-api/src/coconut/dkg/controller/mod.rs similarity index 79% rename from nym-api/src/coconut/dkg/controller.rs rename to nym-api/src/coconut/dkg/controller/mod.rs index ced64f4600..ac94e024a8 100644 --- a/nym-api/src/coconut/dkg/controller.rs +++ b/nym-api/src/coconut/dkg/controller/mod.rs @@ -18,25 +18,12 @@ use nym_coconut_dkg_common::types::EpochState; use nym_crypto::asymmetric::identity; use nym_dkg::bte::keys::KeyPair as DkgKeyPair; use nym_task::{TaskClient, TaskManager}; -use rand::rngs::OsRng; use rand::{CryptoRng, RngCore}; use std::path::PathBuf; use std::time::{Duration, SystemTime}; use tokio::time::interval; -pub(crate) fn init_keypair(config: &config::CoconutSigner) -> Result<()> { - let mut rng = OsRng; - let dkg_params = nym_dkg::bte::setup(); - let kp = DkgKeyPair::new(&dkg_params, &mut rng); - nym_pemstore::store_keypair( - &kp, - &nym_pemstore::KeyPairPath::new( - &config.storage_paths.decryption_key_path, - &config.storage_paths.public_key_with_proof_path, - ), - )?; - Ok(()) -} +pub(crate) mod keys; pub(crate) struct DkgController { dkg_client: DkgClient, @@ -48,10 +35,11 @@ pub(crate) struct DkgController { } impl DkgController { - pub(crate) async fn new( + pub(crate) fn new( config: &config::CoconutSigner, nyxd_client: nyxd::Client, coconut_keypair: CoconutKeyPair, + dkg_keypair: DkgKeyPair, identity_key: identity::PublicKey, rng: R, ) -> Result { @@ -59,18 +47,6 @@ impl DkgController { bail!("can't start a DKG controller without specifying an announce address!") }; - let dkg_keypair = nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - &config.storage_paths.decryption_key_path, - &config.storage_paths.public_key_with_proof_path, - ))?; - if let Ok(coconut_keypair_value) = - nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - &config.storage_paths.secret_key_path, - &config.storage_paths.verification_key_path, - )) - { - coconut_keypair.set(Some(coconut_keypair_value)).await; - } let persistent_state = PersistentState::load_from_file(&config.storage_paths.dkg_persistent_state_path) .unwrap_or_default(); @@ -92,12 +68,12 @@ impl DkgController { }) } - async fn dump_persistent_state(&self) { - if !self.state.coconut_keypair_is_some().await { - // Delete the files just in case the process is killed before the new keys are generated - std::fs::remove_file(&self.secret_key_path).ok(); - std::fs::remove_file(&self.verification_key_path).ok(); - } + fn persist_state(&self) { + // if !self.state.coconut_keypair_is_some().await { + // // Delete the files just in case the process is killed before the new keys are generated + // std::fs::remove_file(&self.secret_key_path).ok(); + // std::fs::remove_file(&self.verification_key_path).ok(); + // } let persistent_state = PersistentState::from(&self.state); if let Err(err) = persistent_state.save_to_file(self.state.persistent_state_path()) { warn!("Could not backup the state for this iteration: {err}"); @@ -170,7 +146,7 @@ impl DkgController { self.state.set_was_in_progress(); // We're dumping state here so that we don't do it uselessly during the // long InProgress state - self.dump_persistent_state().await; + self.persist_state(); Ok(()) } }; @@ -179,7 +155,7 @@ impl DkgController { } else if epoch.state != EpochState::InProgress && epoch.state != EpochState::WaitingInitialisation { - self.dump_persistent_state().await; + self.persist_state(); } if let Ok(current_timestamp) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { @@ -205,12 +181,11 @@ impl DkgController { } } - // TODO: can we make it non-async? it seems we'd have to modify `coconut_keypair.set(coconut_keypair_value)` in new - // could we do it? - pub(crate) async fn start( + pub(crate) fn start( config: &config::CoconutSigner, nyxd_client: nyxd::Client, coconut_keypair: CoconutKeyPair, + dkg_bte_keypair: DkgKeyPair, identity_key: identity::PublicKey, rng: R, shutdown: &TaskManager, @@ -219,8 +194,14 @@ impl DkgController { R: Sync + Send + 'static, { let shutdown_listener = shutdown.subscribe(); - let dkg_controller = - DkgController::new(config, nyxd_client, coconut_keypair, identity_key, rng).await?; + let dkg_controller = DkgController::new( + config, + nyxd_client, + coconut_keypair, + dkg_bte_keypair, + identity_key, + rng, + )?; tokio::spawn(async move { dkg_controller.run(shutdown_listener).await }); Ok(()) } diff --git a/nym-api/src/main.rs b/nym-api/src/main.rs index 032eba869b..3e25a2634c 100644 --- a/nym-api/src/main.rs +++ b/nym-api/src/main.rs @@ -4,6 +4,7 @@ #[macro_use] extern crate rocket; +use crate::coconut::dkg::controller::keys::{load_bte_keypair, load_coconut_keypair_if_exists}; use crate::epoch_operations::RewardedSetUpdater; use crate::network::models::NetworkDetails; use crate::node_describe_cache::DescribedNodes; @@ -68,7 +69,13 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result let nym_network_details = NymNetworkDetails::new_from_env(); let network_details = NetworkDetails::new(connected_nyxd.to_string(), nym_network_details); - let coconut_keypair = coconut::keypair::KeyPair::new(); + let coconut_keypair_wrapper = coconut::keypair::KeyPair::new(); + + // if the keypair doesnt exist (because say this API is running in the caching mode), nothing will happen + if let Some(loaded_keys) = load_coconut_keypair_if_exists(&config.coconut_signer)? { + coconut_keypair_wrapper.set(Some(loaded_keys)).await + } + let identity_keypair = config.base.storage_paths.load_identity()?; let identity_public_key = *identity_keypair.public_key(); @@ -78,7 +85,7 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result network_details, nyxd_client.clone(), identity_keypair, - coconut_keypair.clone(), + coconut_keypair_wrapper.clone(), ) .await?; @@ -134,15 +141,17 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result // start dkg task if config.coconut_signer.enabled { + let dkg_bte_keypair = load_bte_keypair(&config.coconut_signer)?; + DkgController::start( &config.coconut_signer, nyxd_client.clone(), - coconut_keypair, + coconut_keypair_wrapper, + dkg_bte_keypair, identity_public_key, OsRng, &shutdown, - ) - .await?; + )?; } // and then only start the uptime updater (and the monitor itself, duh) diff --git a/nym-api/src/support/config/helpers.rs b/nym-api/src/support/config/helpers.rs index 47b9d25557..a124a8e4dd 100644 --- a/nym-api/src/support/config/helpers.rs +++ b/nym-api/src/support/config/helpers.rs @@ -1,22 +1,26 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use crate::coconut::dkg::controller::keys::init_bte_keypair; use crate::support::config; use crate::support::config::{ default_config_directory, default_data_directory, upgrade_helpers, Config, }; use anyhow::{Context, Result}; use nym_crypto::asymmetric::identity; -use rand_07::rngs::OsRng; +use rand::rngs::OsRng; +use rand_07::rngs::OsRng as OsRng07; use std::{fs, io}; +// TODO: once we upgrade ed25519 library, we could use the same rand library and use proper +// bound fn init_identity_keys(config: &config::NymApiPaths) -> Result<()> { let keypaths = nym_pemstore::KeyPairPath::new( &config.private_identity_key_file, &config.public_identity_key_file, ); - let mut rng = OsRng; + let mut rng = OsRng07; let keypair = identity::KeyPair::new(&mut rng); nym_pemstore::store_keypair(&keypair, &keypaths) .context("failed to store identity keys of the nym api")?; @@ -38,7 +42,8 @@ pub(crate) fn initialise_new(id: &str) -> Result { init_identity_keys(&config.base.storage_paths)?; // create DKG BTE keys - crate::coconut::dkg::controller::init_keypair(&config.coconut_signer)?; + let mut rng = OsRng; + init_bte_keypair(&mut rng, &config.coconut_signer)?; Ok(config) }