Skip to content

Commit

Permalink
Merge pull request #1123 from dusk-network/embed-recovery
Browse files Browse the repository at this point in the history
Embed rusk-recovery binary
  • Loading branch information
herr-seppia authored Nov 9, 2023
2 parents 9d68fc6 + b05796b commit 57e38c3
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 7 deletions.
2 changes: 1 addition & 1 deletion rusk-recovery/src/bin/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct Cli {
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
task::run(
|| Ok(rusk_recovery_tools::keys::exec(args.keep)?),
|| rusk_recovery_tools::keys::exec(args.keep),
args.profile,
args.verbose,
)
Expand Down
6 changes: 4 additions & 2 deletions rusk-recovery/src/bin/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use std::{fs, path::PathBuf};
use tracing::info;
use version::VERSION_BUILD;

use rusk_recovery_tools::state::{deploy, restore_state, tar, Snapshot};
use rusk_recovery_tools::state::{
deploy, restore_state, tar, Snapshot, DEFAULT_SNAPSHOT,
};

#[derive(Parser, Debug)]
#[clap(name = "rusk-recovery-state")]
Expand Down Expand Up @@ -55,7 +57,7 @@ fn main() -> Result<(), Box<dyn Error>> {

let config = match args.init {
Some(path) => fs::read_to_string(path)?,
None => include_str!("../../config/testnet_remote.toml").into(),
None => DEFAULT_SNAPSHOT.into(),
};
let snapshot = toml::from_str(&config)?;

Expand Down
2 changes: 1 addition & 1 deletion rusk-recovery/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn run_stored_circuits_checks(
check_circuits_cache(circuit_list).map(|_| ())
}

pub fn exec(keep_circuits: bool) -> Result<(), io::Error> {
pub fn exec(keep_circuits: bool) -> Result<(), Box<dyn std::error::Error>> {
// This force init is needed to check CRS and create it (if not available)
// See also: https://github.com/dusk-network/rusk/issues/767
Lazy::force(&PUB_PARAMS);
Expand Down
2 changes: 2 additions & 0 deletions rusk-recovery/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub mod tar;
mod zip;

pub const MINIMUM_STAKE: Dusk = dusk(1000.0);
pub const DEFAULT_SNAPSHOT: &str =
include_str!("../config/testnet_remote.toml");

const GENESIS_BLOCK_HEIGHT: u64 = 0;

Expand Down
8 changes: 5 additions & 3 deletions rusk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ async-graphql = "5.0"


## Ephemeral dependencies
rusk-recovery = { version = "0.6", path = "../rusk-recovery", features = ["state"], optional = true}
tempfile = { version = "3.2", optional = true }
rusk-recovery = { version = "0.6", path = "../rusk-recovery", optional = true}

[dev-dependencies]
test-context = "0.1"
Expand All @@ -85,5 +85,7 @@ ff = { version = "0.13", default-features = false }
rustc_tools_util = "0.3"

[features]
default = ["ephemeral"]
ephemeral = ["dep:rusk-recovery", "dep:tempfile"]
default = ["ephemeral", "recovery-state", "recovery-keys"]
ephemeral = ["dep:rusk-recovery", "dep:tempfile", "recovery-state"]
recovery-state = ["rusk-recovery/state", "dep:tempfile"]
recovery-keys = ["rusk-recovery/keys"]
10 changes: 10 additions & 0 deletions rusk/src/bin/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

#[cfg(any(feature = "recovery-state", feature = "recovery-keys"))]
mod command;
#[cfg(feature = "recovery-state")]
mod state;

use std::path::PathBuf;

use clap::builder::PossibleValuesParser;
Expand Down Expand Up @@ -83,4 +88,9 @@ pub struct Args {
#[clap(short = 'n', long = "network-id")]
/// Kadcast network id
pub kadcast_network_id: Option<u8>,

#[cfg(any(feature = "recovery-state", feature = "recovery-keys"))]
/// Command
#[clap(subcommand)]
pub command: Option<command::Command>,
}
78 changes: 78 additions & 0 deletions rusk/src/bin/args/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use clap::builder::BoolishValueParser;
use clap::Subcommand;
use rusk_recovery_tools::Theme;
use std::io;
use tracing::info;

#[allow(clippy::large_enum_variant)]
#[derive(PartialEq, Eq, Hash, Clone, Subcommand, Debug)]
pub enum Command {
#[cfg(feature = "recovery-keys")]
RecoveryKeys {
/// Keeps untracked keys
#[clap(short, long, value_parser = BoolishValueParser::new(), env = "RUSK_KEEP_KEYS")]
keep: bool,
},

#[cfg(feature = "recovery-state")]
RecoveryState {
/// Forces a build/download even if the state is in the profile path.
#[clap(short = 'f', value_parser = BoolishValueParser::new(), long, env = "RUSK_FORCE_STATE")]
force: bool,

/// Create a state applying the init config specified in this file.
#[clap(short, long, value_parser, env = "RUSK_RECOVERY_INPUT")]
init: Option<super::PathBuf>,

/// If specified, the generated state is written on this file instead
/// of save the state in the profile path.
#[clap(short, long, value_parser, num_args(1))]
output: Option<super::PathBuf>,
},
}

impl Command {
fn display_env(theme: &Theme) -> io::Result<()> {
let profile_dir = rusk_profile::get_rusk_profile_dir()?;
let circuits_dir = rusk_profile::get_rusk_circuits_dir()?;
let keys_dir = rusk_profile::get_rusk_keys_dir()?;
let state_dir = rusk_profile::get_rusk_state_dir()?;

info!("{} {}", theme.info("PROFILE"), profile_dir.display());
info!("{} {}", theme.info("CIRCUITS"), circuits_dir.display());
info!("{} {}", theme.info("KEYS"), keys_dir.display());
info!("{} {}", theme.info("STATE"), state_dir.display());
Ok(())
}

pub fn run(self) -> Result<(), Box<dyn std::error::Error>> {
let theme = Theme::default();

Self::display_env(&theme)?;

let result = match self {
#[cfg(feature = "recovery-state")]
Self::RecoveryState {
force,
init,
output,
} => super::state::recovery_state(init, force, output),
#[cfg(feature = "recovery-keys")]
Self::RecoveryKeys { keep } => {
rusk_recovery_tools::keys::exec(keep)
}
};

if let Err(e) = &result {
tracing::error!("{} {e}", theme.error("Error"));
}

result
}
}
104 changes: 104 additions & 0 deletions rusk/src/bin/args/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use super::*;

use std::{env, fs, io};

use rusk_recovery_tools::state::{deploy, restore_state, tar};
use rusk_recovery_tools::Theme;
use tracing::info;

pub fn recovery_state(
init: Option<PathBuf>,
force: bool,
output_file: Option<PathBuf>,
) -> Result<(), Box<dyn std::error::Error>> {
let config = match &init {
Some(path) => fs::read_to_string(path)
.map_err(|_| format!("file {path:?} not found"))?,
None => rusk_recovery_tools::state::DEFAULT_SNAPSHOT.into(),
};
let init = toml::from_str(&config)?;

let theme = Theme::default();
info!("{} Network state", theme.action("Checking"));

let _tmpdir = match output_file.clone() {
Some(output) if output.exists() => Err("Output already exists")?,
Some(_) => {
let tmp_dir = tempfile::tempdir()?;
env::set_var("RUSK_STATE_PATH", tmp_dir.path());
Some(tmp_dir)
}
None => None,
};

if force {
clean_state()?;
}

let state_dir = rusk_profile::get_rusk_state_dir()?;
let state_id_path = rusk_profile::to_rusk_state_id_path(&state_dir);

let _ = rusk_abi::new_vm(&state_dir)?;

// if the state already exists in the expected path, stop early.
if state_dir.exists() && state_id_path.exists() {
info!("{} existing state", theme.info("Found"));

let (_, commit_id) = restore_state(state_dir)?;
info!(
"{} state id at {}",
theme.success("Checked"),
state_id_path.display()
);
info!("{} {}", theme.action("Root"), hex::encode(commit_id));

return Ok(());
}

info!("{} new state", theme.info("Building"));

let (_, commit_id) = deploy(&state_dir, &init)?;

info!("{} {}", theme.action("Final Root"), hex::encode(commit_id));

info!(
"{} network state at {}",
theme.success("Stored"),
state_dir.display()
);
info!(
"{} persisted id at {}",
theme.success("Stored"),
state_id_path.display()
);

if let Some(output) = output_file {
let state_folder = rusk_profile::get_rusk_state_dir()?;
info!(
"{} state into {}",
theme.info("Compressing"),
output.display()
);
tar::archive(&state_folder, &output)?;
}

Ok(())
}

fn clean_state() -> Result<(), io::Error> {
let state_path = rusk_profile::get_rusk_state_dir()?;

fs::remove_dir_all(state_path).or_else(|e| {
if e.kind() == io::ErrorKind::NotFound {
Ok(())
} else {
Err(e)
}
})
}
13 changes: 13 additions & 0 deletions rusk/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
.with_env_filter(EnvFilter::new(log_filter).add_directive(log.into()));

#[cfg(any(feature = "recovery-state", feature = "recovery-keys"))]
// Set custom tracing format if subcommand is specified
if let Some(command) = args.command {
let subscriber = subscriber
.with_level(false)
.without_time()
.with_target(false)
.finish();
tracing::subscriber::set_global_default(subscriber)?;
command.run()?;
return Ok(());
}

// Set the subscriber as global.
// so this subscriber will be used as the default in all threads for the
// remainder of the duration of the program, similar to how `loggers`
Expand Down

0 comments on commit 57e38c3

Please sign in to comment.