cli/commands/replay/
replay_state_with_input_actions.rs

1use node::BuildEnv;
2use openmina_node_native::replay_state_with_input_actions;
3
4#[derive(Debug, clap::Args)]
5/// Replay node using initial state and input actions.
6pub struct ReplayStateWithInputActions {
7    #[arg(long, short, default_value = "~/.openmina/recorder")]
8    pub dir: String,
9
10    #[arg(long, default_value = "./target/release/libreplay_dynamic_effects.so")]
11    pub dynamic_effects_lib: String,
12
13    #[arg(long)]
14    pub ignore_mismatch: bool,
15
16    /// Verbosity level
17    #[arg(long, short, default_value = "info")]
18    pub verbosity: tracing::Level,
19}
20
21impl ReplayStateWithInputActions {
22    pub fn run(self) -> anyhow::Result<()> {
23        openmina_node_native::tracing::initialize(self.verbosity);
24
25        let dir = shellexpand::full(&self.dir)?.into_owned();
26        let dynamic_effects_lib = shellexpand::full(&self.dynamic_effects_lib)?.into_owned();
27
28        let dynamic_effects_lib = match std::path::Path::new(&dynamic_effects_lib).exists() {
29            true => Some(dynamic_effects_lib),
30            false => {
31                eprintln!("dynamic effects compiled lib not found! try running `cargo build --release -p replay_dynamic_effects`");
32                None
33            }
34        };
35
36        replay_state_with_input_actions(
37            &dir,
38            dynamic_effects_lib,
39            self.ignore_mismatch,
40            check_build_env,
41        )?;
42
43        Ok(())
44    }
45}
46
47pub fn check_build_env(
48    record_env: &BuildEnv,
49    replay_env: &BuildEnv,
50    ignore_mismatch: bool,
51) -> anyhow::Result<()> {
52    let is_git_same = record_env.git.commit_hash == replay_env.git.commit_hash;
53    let is_cargo_same = record_env.cargo == replay_env.cargo;
54    let is_rustc_same = record_env.rustc == replay_env.rustc;
55
56    if !is_git_same {
57        let diff = format!(
58            "recorded:\n{:?}\n\ncurrent:\n{:?}",
59            record_env.git, replay_env.git
60        );
61        let msg = format!("git build env mismatch!\n{diff}");
62        if ignore_mismatch {
63        } else if console::user_attended() {
64            use dialoguer::Confirm;
65
66            let prompt = format!("{msg}\nDo you want to continue?");
67            if Confirm::new().with_prompt(prompt).interact().unwrap() {
68            } else {
69                anyhow::bail!("mismatch rejected");
70            }
71        } else {
72            anyhow::bail!("mismatch rejected automatically");
73        }
74    }
75
76    if !is_cargo_same {
77        let diff = format!(
78            "recorded:\n{:?}\n\ncurrent:\n{:?}",
79            record_env.cargo, replay_env.cargo
80        );
81        let msg = format!("cargo build env mismatch!\n{diff}");
82        eprintln!("{msg}");
83    }
84
85    if !is_rustc_same {
86        let diff = format!(
87            "recorded:\n{:?}\n\ncurrent:\n{:?}",
88            record_env.rustc, replay_env.rustc
89        );
90        let msg = format!("rustc build env mismatch!\n{diff}");
91        eprintln!("{msg}");
92    }
93
94    Ok(())
95}