Skip to content

Commit

Permalink
feat: enable specifying debug mode via cli option (#1502)
Browse files Browse the repository at this point in the history
  • Loading branch information
yasonk authored Sep 24, 2024
1 parent 8e9fe06 commit c6e2bc8
Show file tree
Hide file tree
Showing 15 changed files with 154 additions and 32 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
- Updated `miden_core::utils` to re-export `std::sync::LazyLock` and `racy_lock::RacyLock as LazyLock` for std and no_std environments, respectively (#1463).
- Made the undocumented behavior of the VM with regard to undefined behavior of u32 operations, stricter (#1480)
- Introduced the `Emit` instruction (#1496)
- Debug instructions can be enabled in the cli `run` command using `--debug` flag (#1502)
- [BREAKING] ExecutionOptions::new constructor requires a boolean to explicitly set debug mode (#1502)
- [BREAKING] The `run` and the `prove` commands in the cli will accept `--trace` flag instead of `--tracing` (#1502)


#### Fixes

Expand All @@ -27,7 +31,6 @@

- Added `PartialEq`, `Eq`, `Serialize` and `Deserialize` to `AdviceMap` and `AdviceInputs` structs (#1494).


## 0.10.5 (2024-08-21)

#### Enhancements
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ test-skip-proptests: ## Runs all tests, except property-based tests
test-loom: ## Runs all loom-based tests
RUSTFLAGS="--cfg loom" cargo nextest run --cargo-profile test-release --features testing -E 'test(#*loom)'

.PHONY: test-package
test-package: ## Tests specific package: make test-package package=miden-vm
$(DEBUG_ASSERTIONS) cargo nextest run --cargo-profile test-release --features testing -p $(package)

# --- checking ------------------------------------------------------------------------------------

.PHONY: check
Expand Down
3 changes: 2 additions & 1 deletion air/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ impl ExecutionOptions {
max_cycles: Option<u32>,
expected_cycles: u32,
enable_tracing: bool,
enable_debugging: bool,
) -> Result<Self, ExecutionOptionsError> {
let max_cycles = max_cycles.unwrap_or(u32::MAX);
if max_cycles < MIN_TRACE_LEN as u32 {
Expand All @@ -209,7 +210,7 @@ impl ExecutionOptions {
max_cycles,
expected_cycles,
enable_tracing,
enable_debugging: false,
enable_debugging,
})
}

Expand Down
28 changes: 24 additions & 4 deletions docs/src/intro/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Internally, Miden VM uses [rayon](https://github.com/rayon-rs/rayon) for paralle

### GPU acceleration

Miden VM proof generation can be accelerated via GPUs. Currently, GPU acceleration is enabled only on Apple silicon hardware (via [Metal](<https://en.wikipedia.org/wiki/Metal_(API)>)). To compile Miden VM with Metal acceleration enabled, you can run the following command:
Miden VM proof generation can be accelerated via GPUs. Currently, GPU acceleration is enabled only on Apple Silicon hardware (via [Metal](<https://en.wikipedia.org/wiki/Metal_(API)>)). To compile Miden VM with Metal acceleration enabled, you can run the following command:

```
make exec-metal
Expand Down Expand Up @@ -85,7 +85,7 @@ Currently, Miden VM can be executed with the following subcommands:
- `debug` - this will instantiate a [Miden debugger](../tools/debugger.md) against the specified Miden assembly program and inputs.
- `analyze` - this will run a Miden assembly program against specific inputs and will output stats about its execution.
- `repl` - this will initiate the [Miden REPL](../tools/repl.md) tool.
- `example` - this will execute a Miden assembly example program, generate a STARK proof of execution and verify it. Currently it is possible to run `blake3` and `fibonacci` examples.
- `example` - this will execute a Miden assembly example program, generate a STARK proof of execution and verify it. Currently, it is possible to run `blake3` and `fibonacci` examples.

All of the above subcommands require various parameters to be provided. To get more detailed help on what is needed for a given subcommand, you can run the following:

Expand All @@ -111,6 +111,14 @@ MIDEN_LOG=trace ./target/optimized/miden [subcommand] [parameters]

If the level is not specified, `warn` level is set as default.

#### Enable Debugging features

You can use the run command with `--debug` parameter to enable debugging with the [debug instruction](../user_docs/assembly/debugging.md) such as `debug.stack`:

```shell
./target/optimized/miden run -a [path_to.masm] --debug
```

### Inputs

As described [here](https://0xpolygonmiden.github.io/miden-vm/intro/overview.html#inputs-and-outputs) the Miden VM can consume public and secret inputs.
Expand All @@ -133,16 +141,28 @@ After a program finishes executing, the elements that remain on the stack become

In the `miden/examples/fib` directory, we provide a very simple Fibonacci calculator example. This example computes the 1001st term of the Fibonacci sequence. You can execute this example on Miden VM like so:

```
```shell
./target/optimized/miden run -a miden/examples/fib/fib.masm -n 1
```

### Capturing Output

This will run the example code to completion and will output the top element remaining on the stack.

If you want the output of the program in a file, you can use the `--output` or `-o` flag and specify the path to the output file. For example:

```
```shell
./target/optimized/miden run -a miden/examples/fib/fib.masm -o fib.out
```

This will dump the output of the program into the `fib.out` file. The output file will contain the state of the stack at the end of the program execution.

### Running with debug instruction enabled

Inside `miden/examples/fib/fib.masm`, insert `debug.stack` instruction anywhere between `begin` and `end`. Then run:

```shell
./target/optimized/miden run -a miden/examples/fib/fib.masm -n 1 --debug
```

You should see output similar to "Stack state before step ..."
2 changes: 1 addition & 1 deletion docs/src/user_docs/assembly/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ trace.EVENT_ID_1
trace.2
```

To make use of the `trace` instruction, programs should be ran with tracing flag (`-t` or `--tracing`), otherwise these instructions will be ignored.
To make use of the `trace` instruction, programs should be ran with tracing flag (`-t` or `--trace`), otherwise these instructions will be ignored.
2 changes: 1 addition & 1 deletion miden/src/cli/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl CompileCmd {
let libraries = Libraries::new(&self.library_paths)?;

// compile the program
let compiled_program = program.compile(&Debug::Off, &libraries.libraries)?;
let compiled_program = program.compile(Debug::Off, &libraries.libraries)?;

// report program hash to user
let program_hash: [u8; 32] = compiled_program.hash().into();
Expand Down
25 changes: 23 additions & 2 deletions miden/src/cli/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ impl Debug {
}
}

impl From<bool> for Debug {
fn from(value: bool) -> Self {
match value {
true => Debug::On,
false => Debug::Off,
}
}
}

// MERKLE DATA
// ================================================================================================

Expand Down Expand Up @@ -416,7 +425,7 @@ impl ProgramFile {

/// Compiles this program file into a [Program].
#[instrument(name = "compile_program", skip_all)]
pub fn compile<'a, I>(&self, debug: &Debug, libraries: I) -> Result<Program, Report>
pub fn compile<'a, I>(&self, debug: Debug, libraries: I) -> Result<Program, Report>
where
I: IntoIterator<Item = &'a Library>,
{
Expand Down Expand Up @@ -552,7 +561,7 @@ impl Libraries {
// ================================================================================================
#[cfg(test)]
mod test {
use super::InputFile;
use super::{Debug, InputFile};

#[test]
fn test_merkle_data_parsing() {
Expand Down Expand Up @@ -626,4 +635,16 @@ mod test {
let merkle_store = inputs.parse_merkle_store().unwrap();
assert!(merkle_store.is_some());
}

#[test]
fn test_debug_from_true() {
let debug_mode: Debug = true.into(); // true.into() will also test Debug.from(true)
assert!(matches!(debug_mode, Debug::On));
}

#[test]
fn test_debug_from_false() {
let debug_mode: Debug = false.into(); // false.into() will also test Debug.from(false)
assert!(matches!(debug_mode, Debug::Off));
}
}
2 changes: 1 addition & 1 deletion miden/src/cli/debug/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl DebugCmd {

// load program from file and compile
let program = ProgramFile::read_with(self.assembly_file.clone(), source_manager.clone())?
.compile(&Debug::On, &libraries.libraries)?;
.compile(Debug::On, &libraries.libraries)?;

let program_hash: [u8; 32] = program.hash().into();
println!("Debugging program with hash {}...", hex::encode(program_hash));
Expand Down
8 changes: 4 additions & 4 deletions miden/src/cli/prove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ pub struct ProveCmd {
security: String,

/// Enable tracing to monitor execution of the VM
#[clap(short = 't', long = "tracing")]
tracing: bool,
#[clap(short = 't', long = "trace")]
trace: bool,
}

impl ProveCmd {
pub fn get_proof_options(&self) -> Result<ProvingOptions, ExecutionOptionsError> {
let exec_options =
ExecutionOptions::new(Some(self.max_cycles), self.expected_cycles, self.tracing)?;
ExecutionOptions::new(Some(self.max_cycles), self.expected_cycles, self.trace, false)?;
Ok(match self.security.as_str() {
"96bits" => {
if self.rpx {
Expand Down Expand Up @@ -145,7 +145,7 @@ fn load_data(params: &ProveCmd) -> Result<(Program, InputFile), Report> {

// load program from file and compile
let program =
ProgramFile::read(&params.assembly_file)?.compile(&Debug::Off, &libraries.libraries)?;
ProgramFile::read(&params.assembly_file)?.compile(Debug::Off, &libraries.libraries)?;

// load input data from file
let input_data = InputFile::read(&params.input_file, &params.assembly_file)?;
Expand Down
25 changes: 16 additions & 9 deletions miden/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use assembly::diagnostics::{IntoDiagnostic, Report, WrapErr};
use clap::Parser;
use processor::{DefaultHost, ExecutionOptions, ExecutionTrace};

use super::data::{instrument, Debug, InputFile, Libraries, OutputFile, ProgramFile};
use super::data::{instrument, InputFile, Libraries, OutputFile, ProgramFile};

#[derive(Debug, Clone, Parser)]
#[clap(about = "Run a miden program")]
Expand Down Expand Up @@ -38,8 +38,12 @@ pub struct RunCmd {
output_file: Option<PathBuf>,

/// Enable tracing to monitor execution of the VM
#[clap(short = 't', long = "tracing")]
tracing: bool,
#[clap(short = 't', long = "trace")]
trace: bool,

/// Enable debug instructions
#[clap(short = 'd', long = "debug")]
debug: bool,
}

impl RunCmd {
Expand Down Expand Up @@ -106,16 +110,19 @@ fn run_program(params: &RunCmd) -> Result<(ExecutionTrace, [u8; 32]), Report> {
let libraries = Libraries::new(&params.library_paths)?;

// load program from file and compile
let program =
ProgramFile::read(&params.assembly_file)?.compile(&Debug::Off, &libraries.libraries)?;
let program = ProgramFile::read(&params.assembly_file)?
.compile(params.debug.into(), &libraries.libraries)?;

// load input data from file
let input_data = InputFile::read(&params.input_file, &params.assembly_file)?;

// get execution options
let execution_options =
ExecutionOptions::new(Some(params.max_cycles), params.expected_cycles, params.tracing)
.into_diagnostic()?;
let execution_options = ExecutionOptions::new(
Some(params.max_cycles),
params.expected_cycles,
params.trace,
params.debug,
)
.into_diagnostic()?;

// fetch the stack and program inputs from the arguments
let stack_inputs = input_data.parse_stack_inputs().map_err(Report::msg)?;
Expand Down
8 changes: 6 additions & 2 deletions miden/src/examples/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ pub enum ExampleType {

impl ExampleOptions {
pub fn get_proof_options(&self) -> Result<ProvingOptions, ExecutionOptionsError> {
let exec_options =
ExecutionOptions::new(Some(self.max_cycles), self.expected_cycles, self.tracing)?;
let exec_options = ExecutionOptions::new(
Some(self.max_cycles),
self.expected_cycles,
self.tracing,
false,
)?;
Ok(match self.security.as_str() {
"96bits" => {
if self.rpx {
Expand Down
55 changes: 52 additions & 3 deletions miden/tests/integration/operations/decorators/events.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use assembly::Assembler;
use processor::{ExecutionOptions, Program};
use prover::StackInputs;

use super::TestHost;

Expand All @@ -16,7 +17,8 @@ fn test_event_handling() {
// compile and execute program
let program: Program = Assembler::default().assemble_program(source).unwrap();
let mut host = TestHost::default();
processor::execute(&program, Default::default(), &mut host, Default::default()).unwrap();
processor::execute(&program, StackInputs::default(), &mut host, ExecutionOptions::default())
.unwrap();

// make sure events were handled correctly
let expected = vec![1, 2];
Expand All @@ -38,18 +40,65 @@ fn test_trace_handling() {
let mut host = TestHost::default();

// execute program with disabled tracing
processor::execute(&program, Default::default(), &mut host, Default::default()).unwrap();
processor::execute(&program, StackInputs::default(), &mut host, ExecutionOptions::default())
.unwrap();
let expected = Vec::<u32>::new();
assert_eq!(host.trace_handler, expected);

// execute program with enabled tracing
processor::execute(
&program,
Default::default(),
StackInputs::default(),
&mut host,
ExecutionOptions::default().with_tracing(),
)
.unwrap();
let expected = vec![1, 2];
assert_eq!(host.trace_handler, expected);
}

#[test]
fn test_debug_with_debugging() {
let source: &str = "\
begin
push.1
debug.stack
debug.mem
end";

// compile and execute program
let program: Program =
Assembler::default().with_debug_mode(true).assemble_program(source).unwrap();
let mut host = TestHost::default();
processor::execute(
&program,
StackInputs::default(),
&mut host,
ExecutionOptions::default().with_debugging(),
)
.unwrap();

// Expect to see the debug.stack and debug.mem commands
let expected = vec!["stack", "mem"];
assert_eq!(host.debug_handler, expected);
}

#[test]
fn test_debug_without_debugging() {
let source: &str = "\
begin
push.1
debug.stack
debug.mem
end";

// compile and execute program
let program: Program = Assembler::default().assemble_program(source).unwrap();
let mut host = TestHost::default();
processor::execute(&program, StackInputs::default(), &mut host, ExecutionOptions::default())
.unwrap();

// Expect to see no debug commands
let expected: Vec<String> = vec![];
assert_eq!(host.debug_handler, expected);
}
Loading

0 comments on commit c6e2bc8

Please sign in to comment.