leo_lang/cli/commands/
debug.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use leo_package::Package;
18
19use snarkvm::prelude::TestnetV0;
20
21use std::path::PathBuf;
22
23use super::*;
24
25/// Debugs an Aleo program through the interpreter.
26#[derive(Parser, Debug)]
27pub struct LeoDebug {
28    #[arg(long, help = "Use these source files instead of finding source files through the project structure. Program submodules aren't supported here.", num_args = 1..)]
29    pub(crate) paths: Vec<String>,
30    #[arg(long, help = "The block height, accessible via block.height.", default_value = "0")]
31    pub(crate) block_height: u32,
32    #[arg(long, action, help = "Use the text user interface.")]
33    pub(crate) tui: bool,
34    #[clap(flatten)]
35    pub(crate) compiler_options: BuildOptions,
36    #[clap(flatten)]
37    pub(crate) env_override: EnvOptions,
38}
39
40impl Command for LeoDebug {
41    type Input = Option<Package>;
42    type Output = ();
43
44    fn log_span(&self) -> Span {
45        tracing::span!(tracing::Level::INFO, "Leo")
46    }
47
48    fn prelude(&self, context: Context) -> Result<Self::Input> {
49        if self.paths.is_empty() {
50            let package = LeoBuild { options: self.compiler_options.clone(), env_override: self.env_override.clone() }
51                .execute(context)?;
52            Ok(Some(package))
53        } else {
54            Ok(None)
55        }
56    }
57
58    fn apply(self, _: Context, input: Self::Input) -> Result<Self::Output> {
59        handle_debug(&self, input)
60    }
61}
62
63fn handle_debug(command: &LeoDebug, package: Option<Package>) -> Result<()> {
64    // Get the network.
65    let network_name = get_network(&command.env_override.network)?;
66
67    if command.paths.is_empty() {
68        let package = package.unwrap();
69
70        // Get the private key.
71        let private_key = get_private_key::<TestnetV0>(&Some(leo_ast::TEST_PRIVATE_KEY.to_string()))?;
72
73        // Get the paths of all local Leo dependencies.
74        let local_dependency_paths = collect_leo_paths(&package);
75        let aleo_paths = collect_aleo_paths(&package);
76
77        // No need to keep this around while the interpreter runs.
78        std::mem::drop(package);
79
80        leo_interpreter::interpret(
81            &local_dependency_paths,
82            &aleo_paths,
83            private_key.to_string(),
84            command.block_height,
85            command.tui,
86            network_name,
87        )
88    } else {
89        // Program that have submodules aren't supported in this mode.
90        let private_key: PrivateKey<TestnetV0> = PrivateKey::from_str(leo_ast::TEST_PRIVATE_KEY)?;
91
92        let leo_paths: Vec<(PathBuf, Vec<PathBuf>)> = command
93            .paths
94            .iter()
95            .filter(|path_str| path_str.ends_with(".leo"))
96            .map(|path_str| (path_str.into(), vec![]))
97            .collect();
98        let aleo_paths: Vec<PathBuf> = command
99            .paths
100            .iter()
101            .filter(|path_str| !path_str.ends_with(".leo"))
102            .map(|path_str| path_str.into())
103            .collect();
104
105        leo_interpreter::interpret(
106            &leo_paths,
107            &aleo_paths,
108            private_key.to_string(),
109            command.block_height,
110            command.tui,
111            network_name,
112        )
113    }
114}