From 363aa865fd0b250c3152c230b649b3668dfae2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Mon, 2 Oct 2023 18:34:20 -0400 Subject: [PATCH 01/19] First cut at implementing a debug command for nargo Allows stepping through the ACIR opcodes, showing the current opcode and mapped source location. --- tooling/nargo/src/errors.rs | 4 + tooling/nargo/src/ops/debug.rs | 157 +++++++++++++++++++++++++ tooling/nargo/src/ops/mod.rs | 2 + tooling/nargo_cli/src/cli/debug_cmd.rs | 117 ++++++++++++++++++ tooling/nargo_cli/src/cli/mod.rs | 3 + 5 files changed, 283 insertions(+) create mode 100644 tooling/nargo/src/ops/debug.rs create mode 100644 tooling/nargo_cli/src/cli/debug_cmd.rs diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index ea6e7fa8108..dd68bfbc037 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -49,6 +49,7 @@ impl NargoError { OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message), OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => Some(reason), }, + ExecutionError::Halted => None, } } } @@ -60,6 +61,9 @@ pub enum ExecutionError { #[error(transparent)] SolvingError(#[from] OpcodeResolutionError), + + #[error("Execution halted")] + Halted, } /// Extracts the opcode locations from a nargo error. diff --git a/tooling/nargo/src/ops/debug.rs b/tooling/nargo/src/ops/debug.rs new file mode 100644 index 00000000000..e289b55430e --- /dev/null +++ b/tooling/nargo/src/ops/debug.rs @@ -0,0 +1,157 @@ +use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}; +use acvm::BlackBoxFunctionSolver; +use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; +use acvm::acir::circuit::OpcodeLocation; + +use crate::artifacts::debug::DebugArtifact; +use crate::errors::ExecutionError; +use crate::NargoError; + +use super::foreign_calls::ForeignCall; + +use std::io::{self, Write}; + +enum SolveResult { + Done, + Ok, +} + +enum Command { + Step, + Continue, + Stop, +} + +pub fn debug_circuit( + blackbox_solver: &B, + circuit: Circuit, + debug_artifact: DebugArtifact, + initial_witness: WitnessMap, + show_output: bool, +) -> Result { + let mut acvm = ACVM::new(blackbox_solver, circuit.opcodes, initial_witness); + + 'outer: loop { + show_current_vm_status(&acvm, &debug_artifact); + let command = match read_command() { + Ok(cmd) => cmd, + Err(err) => { + eprintln!("Error reading command: {}", err); + return Err(NargoError::ExecutionError(ExecutionError::Halted)) + } + }; + match command { + Command::Stop => return Err(NargoError::ExecutionError(ExecutionError::Halted)), + Command::Step => { + match step_opcode(&mut acvm, &circuit.assert_messages, show_output)? { + SolveResult::Done => break, + SolveResult::Ok => {}, + } + } + Command::Continue => { + println!("(Continuing execution...)"); + loop { + match step_opcode(&mut acvm, &circuit.assert_messages, show_output)? { + SolveResult::Done => break 'outer, + SolveResult::Ok => {}, + } + } + }, + } + } + + let solved_witness = acvm.finalize(); + Ok(solved_witness) +} + +fn step_opcode( + acvm: &mut ACVM, + assert_messages: &Vec<(OpcodeLocation, String)>, + show_output: bool, +) -> Result { + // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 + let get_assert_message = |opcode_location| { + assert_messages + .iter() + .find(|(loc, _)| loc == opcode_location) + .map(|(_, message)| message.clone()) + }; + + let solver_status = acvm.solve_opcode(); + + match solver_status { + ACVMStatus::Solved => Ok(SolveResult::Done), + ACVMStatus::InProgress => Ok(SolveResult::Ok), + ACVMStatus::Failure(error) => { + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + } => Some(vec![*opcode_location]), + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + Some(call_stack.clone()) + } + _ => None, + }; + + Err(NargoError::ExecutionError(match call_stack { + Some(call_stack) => { + if let Some(assert_message) = get_assert_message( + call_stack.last().expect("Call stacks should not be empty"), + ) { + ExecutionError::AssertionFailed(assert_message, call_stack) + } else { + ExecutionError::SolvingError(error) + } + } + None => ExecutionError::SolvingError(error), + })) + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let foreign_call_result = ForeignCall::execute(&foreign_call, show_output)?; + acvm.resolve_pending_foreign_call(foreign_call_result); + Ok(SolveResult::Ok) + } + } +} + +fn show_source_code_location(location: &OpcodeLocation, debug_artifact: &DebugArtifact) { + let locations = debug_artifact.debug_symbols[0].opcode_location(&location); + match locations { + Some(locations) => { + for loc in locations { + let file = &debug_artifact.file_map[&loc.file]; + let source = &file.source.as_str(); + let start = loc.span.start() as usize; + let end = loc.span.end() as usize; + println!("At {}:{start}-{end}", file.path.as_path().display()); + println!("\n{}\n", &source[start..end]); + } + }, + None => {} + } +} + +fn show_current_vm_status (acvm: &ACVM, debug_artifact: &DebugArtifact) { + let ip = acvm.instruction_pointer(); + println!("Stopped at opcode {}: {}", ip, acvm.opcodes()[ip]); + show_source_code_location(&OpcodeLocation::Acir(ip), &debug_artifact); +} + +fn read_command() -> Result { + loop { + let mut line = String::new(); + print!(">>> "); + io::stdout().flush().unwrap(); + io::stdin().read_line(&mut line)?; + if line.is_empty() { + return Ok(Command::Stop); + } + match line.trim() { + "s" => return Ok(Command::Step), + "c" => return Ok(Command::Continue), + "q" => return Ok(Command::Stop), + "" => continue, + _ => println!("ERROR: unknown command") + } + } +} diff --git a/tooling/nargo/src/ops/mod.rs b/tooling/nargo/src/ops/mod.rs index f789455577c..16933a8217c 100644 --- a/tooling/nargo/src/ops/mod.rs +++ b/tooling/nargo/src/ops/mod.rs @@ -1,8 +1,10 @@ pub use self::execute::execute_circuit; +pub use self::debug::debug_circuit; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::test::{run_test, TestStatus}; mod execute; +mod debug; mod foreign_calls; mod optimize; mod test; diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs new file mode 100644 index 00000000000..024037d06b6 --- /dev/null +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -0,0 +1,117 @@ +use acvm::acir::native_types::WitnessMap; +use clap::Args; + +use nargo::constants::PROVER_INPUT_FILE; +use nargo::package::Package; +use nargo::artifacts::debug::DebugArtifact; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_abi::input_parser::{Format, InputValue}; +use noirc_abi::InputMap; +use noirc_driver::{CompileOptions, CompiledProgram}; +use noirc_frontend::graph::CrateName; + +use super::compile_cmd::compile_bin_package; +use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; +use super::NargoConfig; +use crate::backends::Backend; +use crate::errors::CliError; + +/// Executes a circuit in debug mode +#[derive(Debug, Clone, Args)] +pub(crate) struct DebugCommand { + /// Write the execution witness to named file + witness_name: Option, + + /// The name of the toml file which contains the inputs for the prover + #[clap(long, short, default_value = PROVER_INPUT_FILE)] + prover_name: String, + + /// The name of the package to execute + #[clap(long)] + package: Option, + + #[clap(flatten)] + compile_options: CompileOptions, +} + +pub(crate) fn run( + backend: &Backend, + args: DebugCommand, + config: NargoConfig, +) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package.map_or(PackageSelection::DefaultOrAll, PackageSelection::Selected); + let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let target_dir = &workspace.target_directory_path(); + + let (np_language, opcode_support) = backend.get_backend_info()?; + for package in &workspace { + let compiled_program = compile_bin_package( + &workspace, + package, + &args.compile_options, + true, + np_language, + &|opcode| opcode_support.is_opcode_supported(opcode), + )?; + + println!("[{}] Starting debugger", package.name); + let (return_value, solved_witness) = + debug_program_and_decode(compiled_program, package, &args.prover_name)?; + + println!("[{}] Circuit witness successfully solved", package.name); + if let Some(return_value) = return_value { + println!("[{}] Circuit output: {return_value:?}", package.name); + } + if let Some(witness_name) = &args.witness_name { + let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + } + } + Ok(()) +} + +fn debug_program_and_decode( + program: CompiledProgram, + package: &Package, + prover_name: &str, +) -> Result<(Option, WitnessMap), CliError> { + // Parse the initial witness values from Prover.toml + let (inputs_map, _) = + read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; + let solved_witness = debug_program(&program, &inputs_map)?; + let public_abi = program.abi.public_abi(); + let (_, return_value) = public_abi.decode(&solved_witness)?; + + Ok((return_value, solved_witness)) +} + +pub(crate) fn debug_program( + compiled_program: &CompiledProgram, + inputs_map: &InputMap, +) -> Result { + #[allow(deprecated)] + let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); + + let initial_witness = compiled_program.abi.encode(inputs_map, None)?; + + let debug_artifact = DebugArtifact { + debug_symbols: vec![compiled_program.debug.clone()], + file_map: compiled_program.file_map.clone(), + }; + + let solved_witness_err = nargo::ops::debug_circuit( + &blackbox_solver, + compiled_program.circuit.clone(), + debug_artifact, + initial_witness, + true, + ); + match solved_witness_err { + Ok(solved_witness) => Ok(solved_witness), + Err(err) => { + Err(crate::errors::CliError::NargoError(err)) + } + } +} diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 56d36095518..657973a92d0 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -21,6 +21,7 @@ mod new_cmd; mod prove_cmd; mod test_cmd; mod verify_cmd; +mod debug_cmd; const GIT_HASH: &str = env!("GIT_COMMIT"); const IS_DIRTY: &str = env!("GIT_DIRTY"); @@ -58,6 +59,7 @@ enum NargoCommand { New(new_cmd::NewCommand), Init(init_cmd::InitCommand), Execute(execute_cmd::ExecuteCommand), + Debug(debug_cmd::DebugCommand), Prove(prove_cmd::ProveCommand), Verify(verify_cmd::VerifyCommand), Test(test_cmd::TestCommand), @@ -93,6 +95,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { NargoCommand::Check(args) => check_cmd::run(&backend, args, config), NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config), + NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config), NargoCommand::Verify(args) => verify_cmd::run(&backend, args, config), NargoCommand::Test(args) => test_cmd::run(&backend, args, config), From 21571a85a724cdba51f2fb8453908f9e00923c6e Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Tue, 3 Oct 2023 13:18:42 +0200 Subject: [PATCH 02/19] Use ForeignCallExecutor from debug op --- tooling/nargo/src/ops/debug.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tooling/nargo/src/ops/debug.rs b/tooling/nargo/src/ops/debug.rs index e289b55430e..fae53f9916d 100644 --- a/tooling/nargo/src/ops/debug.rs +++ b/tooling/nargo/src/ops/debug.rs @@ -7,7 +7,7 @@ use crate::artifacts::debug::DebugArtifact; use crate::errors::ExecutionError; use crate::NargoError; -use super::foreign_calls::ForeignCall; +use super::foreign_calls::ForeignCallExecutor; use std::io::{self, Write}; @@ -30,6 +30,7 @@ pub fn debug_circuit( show_output: bool, ) -> Result { let mut acvm = ACVM::new(blackbox_solver, circuit.opcodes, initial_witness); + let mut foreign_call_executor = ForeignCallExecutor::default(); 'outer: loop { show_current_vm_status(&acvm, &debug_artifact); @@ -43,7 +44,7 @@ pub fn debug_circuit( match command { Command::Stop => return Err(NargoError::ExecutionError(ExecutionError::Halted)), Command::Step => { - match step_opcode(&mut acvm, &circuit.assert_messages, show_output)? { + match step_opcode(&mut acvm, &circuit.assert_messages, show_output, &mut foreign_call_executor)? { SolveResult::Done => break, SolveResult::Ok => {}, } @@ -51,7 +52,7 @@ pub fn debug_circuit( Command::Continue => { println!("(Continuing execution...)"); loop { - match step_opcode(&mut acvm, &circuit.assert_messages, show_output)? { + match step_opcode(&mut acvm, &circuit.assert_messages, show_output, &mut foreign_call_executor)? { SolveResult::Done => break 'outer, SolveResult::Ok => {}, } @@ -68,6 +69,7 @@ fn step_opcode( acvm: &mut ACVM, assert_messages: &Vec<(OpcodeLocation, String)>, show_output: bool, + foreign_call_executor: &mut ForeignCallExecutor, ) -> Result { // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 let get_assert_message = |opcode_location| { @@ -107,7 +109,7 @@ fn step_opcode( })) } ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = ForeignCall::execute(&foreign_call, show_output)?; + let foreign_call_result = foreign_call_executor.execute(&foreign_call, show_output)?; acvm.resolve_pending_foreign_call(foreign_call_result); Ok(SolveResult::Ok) } From ab59acab0b00c29208dd3df096fee75c273f7f11 Mon Sep 17 00:00:00 2001 From: synthia Date: Mon, 2 Oct 2023 14:34:33 -0700 Subject: [PATCH 03/19] feat(nargo): Stubbed out debug repl with placeholder command --- tooling/nargo_cli/Cargo.toml | 1 + tooling/nargo_cli/src/cli/debug_cmd.rs | 4 ++++ tooling/nargo_cli/src/cli/mod.rs | 2 ++ 3 files changed, 7 insertions(+) diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 0ae6073f0a1..bd9f14b035c 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -36,6 +36,7 @@ serde.workspace = true serde_json.workspace = true prettytable-rs = "0.10" rayon = "1.7.0" +reedline-repl-rs = "1.0.7" thiserror.workspace = true tower.workspace = true async-lsp = { version = "0.0.5", default-features = false, features = [ diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 024037d06b6..8740860c172 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -26,6 +26,10 @@ pub(crate) struct DebugCommand { #[clap(long, short, default_value = PROVER_INPUT_FILE)] prover_name: String, + /// Detail all packages in the workspace + #[clap(long, conflicts_with = "package")] + workspace: bool, + /// The name of the package to execute #[clap(long)] package: Option, diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 657973a92d0..03214dec9c3 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -13,6 +13,7 @@ mod backend_cmd; mod check_cmd; mod codegen_verifier_cmd; mod compile_cmd; +mod debug_cmd; mod execute_cmd; mod info_cmd; mod init_cmd; @@ -94,6 +95,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> { NargoCommand::Init(args) => init_cmd::run(&backend, args, config), NargoCommand::Check(args) => check_cmd::run(&backend, args, config), NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), + NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config), NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config), From afa09641b8b49a969d2b02439e25a21a0f4869ec Mon Sep 17 00:00:00 2001 From: synthia Date: Tue, 3 Oct 2023 14:58:32 -0700 Subject: [PATCH 04/19] refactor debug logic around ReplContext methods --- tooling/nargo/src/ops/debug.rs | 276 +++++++++++++++++-------------- tooling/nargo_cli/src/cli/mod.rs | 1 - 2 files changed, 156 insertions(+), 121 deletions(-) diff --git a/tooling/nargo/src/ops/debug.rs b/tooling/nargo/src/ops/debug.rs index fae53f9916d..7630254925e 100644 --- a/tooling/nargo/src/ops/debug.rs +++ b/tooling/nargo/src/ops/debug.rs @@ -9,151 +9,187 @@ use crate::NargoError; use super::foreign_calls::ForeignCallExecutor; -use std::io::{self, Write}; +use std::rc::Rc; +use std::sync::Mutex; + +use reedline_repl_rs::clap::{ + ArgMatches as ReplArgMatches, + Command as ReplCommand, +}; +use reedline_repl_rs::Repl; enum SolveResult { Done, Ok, } -enum Command { - Step, - Continue, - Stop, -} - -pub fn debug_circuit( - blackbox_solver: &B, - circuit: Circuit, +struct ReplContext<'backend, B: BlackBoxFunctionSolver> { + acvm: Option>, debug_artifact: DebugArtifact, - initial_witness: WitnessMap, + foreign_call_executor: ForeignCallExecutor, + circuit: Circuit, show_output: bool, -) -> Result { - let mut acvm = ACVM::new(blackbox_solver, circuit.opcodes, initial_witness); - let mut foreign_call_executor = ForeignCallExecutor::default(); - - 'outer: loop { - show_current_vm_status(&acvm, &debug_artifact); - let command = match read_command() { - Ok(cmd) => cmd, - Err(err) => { - eprintln!("Error reading command: {}", err); - return Err(NargoError::ExecutionError(ExecutionError::Halted)) - } +} + +impl<'backend, B> ReplContext<'backend, B> where B: BlackBoxFunctionSolver { + fn step_opcode(&mut self) -> Result { + // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 + let assert_messages = &self.circuit.assert_messages; + let get_assert_message = |opcode_location| { + assert_messages + .iter() + .find(|(loc, _)| loc == opcode_location) + .map(|(_, message)| message.clone()) }; - match command { - Command::Stop => return Err(NargoError::ExecutionError(ExecutionError::Halted)), - Command::Step => { - match step_opcode(&mut acvm, &circuit.assert_messages, show_output, &mut foreign_call_executor)? { - SolveResult::Done => break, - SolveResult::Ok => {}, - } - } - Command::Continue => { - println!("(Continuing execution...)"); - loop { - match step_opcode(&mut acvm, &circuit.assert_messages, show_output, &mut foreign_call_executor)? { - SolveResult::Done => break 'outer, - SolveResult::Ok => {}, + + let acvm = self.acvm.as_mut().unwrap(); + let solver_status = acvm.solve_opcode(); + + match solver_status { + ACVMStatus::Solved => Ok(SolveResult::Done), + ACVMStatus::InProgress => Ok(SolveResult::Ok), + ACVMStatus::Failure(error) => { + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + } => Some(vec![*opcode_location]), + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + Some(call_stack.clone()) } - } - }, + _ => None, + }; + + Err(NargoError::ExecutionError(match call_stack { + Some(call_stack) => { + if let Some(assert_message) = get_assert_message( + call_stack.last().expect("Call stacks should not be empty"), + ) { + ExecutionError::AssertionFailed(assert_message, call_stack) + } else { + ExecutionError::SolvingError(error) + } + } + None => ExecutionError::SolvingError(error), + })) + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let foreign_call_result = self.foreign_call_executor.execute(&foreign_call, self.show_output)?; + acvm.resolve_pending_foreign_call(foreign_call_result); + Ok(SolveResult::Ok) + } } } - let solved_witness = acvm.finalize(); - Ok(solved_witness) -} + fn show_current_vm_status(&self) { + let acvm = self.acvm.as_ref().unwrap(); + let ip = acvm.instruction_pointer(); + println!("Stopped at opcode {}: {}", ip, acvm.opcodes()[ip]); + self.show_source_code_location(&OpcodeLocation::Acir(ip)); + } -fn step_opcode( - acvm: &mut ACVM, - assert_messages: &Vec<(OpcodeLocation, String)>, - show_output: bool, - foreign_call_executor: &mut ForeignCallExecutor, -) -> Result { - // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 - let get_assert_message = |opcode_location| { - assert_messages - .iter() - .find(|(loc, _)| loc == opcode_location) - .map(|(_, message)| message.clone()) - }; - - let solver_status = acvm.solve_opcode(); - - match solver_status { - ACVMStatus::Solved => Ok(SolveResult::Done), - ACVMStatus::InProgress => Ok(SolveResult::Ok), - ACVMStatus::Failure(error) => { - let call_stack = match &error { - OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Resolved(opcode_location), - } => Some(vec![*opcode_location]), - OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - Some(call_stack.clone()) - } - _ => None, - }; - - Err(NargoError::ExecutionError(match call_stack { - Some(call_stack) => { - if let Some(assert_message) = get_assert_message( - call_stack.last().expect("Call stacks should not be empty"), - ) { - ExecutionError::AssertionFailed(assert_message, call_stack) - } else { - ExecutionError::SolvingError(error) - } + fn show_source_code_location(&self, location: &OpcodeLocation) { + let locations = self.debug_artifact.debug_symbols[0].opcode_location(&location); + match locations { + Some(locations) => { + for loc in locations { + let file = &self.debug_artifact.file_map[&loc.file]; + let source = &file.source.as_str(); + let start = loc.span.start() as usize; + let end = loc.span.end() as usize; + println!("At {}:{start}-{end}", file.path.as_path().display()); + println!("\n{}\n", &source[start..end]); } - None => ExecutionError::SolvingError(error), - })) - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = foreign_call_executor.execute(&foreign_call, show_output)?; - acvm.resolve_pending_foreign_call(foreign_call_result); - Ok(SolveResult::Ok) + }, + None => {} } } + + fn finalize(&mut self) -> WitnessMap { + self.acvm.take().unwrap().finalize() + } } -fn show_source_code_location(location: &OpcodeLocation, debug_artifact: &DebugArtifact) { - let locations = debug_artifact.debug_symbols[0].opcode_location(&location); - match locations { - Some(locations) => { - for loc in locations { - let file = &debug_artifact.file_map[&loc.file]; - let source = &file.source.as_str(); - let start = loc.span.start() as usize; - let end = loc.span.end() as usize; - println!("At {}:{start}-{end}", file.path.as_path().display()); - println!("\n{}\n", &source[start..end]); - } - }, - None => {} +impl From for NargoError { + fn from(_e: reedline_repl_rs::Error) -> Self { + NargoError::CompilationError } } -fn show_current_vm_status (acvm: &ACVM, debug_artifact: &DebugArtifact) { - let ip = acvm.instruction_pointer(); - println!("Stopped at opcode {}: {}", ip, acvm.opcodes()[ip]); - show_source_code_location(&OpcodeLocation::Acir(ip), &debug_artifact); + +// impl fmt::Display for NargoError { +// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +// match self { +// NargoError::CompilationError => write!(f, "Compilation Error"), +// NargoError::ExecutionError(e) => write!(f, "Execution Error: {}", e), +// NargoError::ForeignCallError(e) => write!(f, "Foreign call Error: {}", e), +// } +// } +// } + +pub fn debug_circuit( + blackbox_solver: &B, + circuit: Circuit, + debug_artifact: DebugArtifact, + initial_witness: WitnessMap, + show_output: bool, +) -> Result { + let opcodes = circuit.opcodes.clone(); + let acvm = ACVM::new(blackbox_solver, opcodes, initial_witness); + let foreign_call_executor = ForeignCallExecutor::default(); + + let repl_context = Rc::new(Mutex::new(ReplContext { + acvm: Some(acvm), + debug_artifact, + foreign_call_executor, + circuit, + show_output, + })); + let mut repl = Repl::new(repl_context.clone()) + .with_name("debug") + .with_version(env!["CARGO_PKG_VERSION"]) + .with_command( + ReplCommand::new("s") + .about("step to the next opcode"), + step_command, + ) + .with_command( + ReplCommand::new("c") + .about("continue execution until the end of the program"), + continue_command, + ) + .with_command( + ReplCommand::new("q") + .about("quit the debugger"), + quit_command, + ); + repl.run().unwrap(); + let solved_witness = repl_context.lock().unwrap().finalize(); + Ok(solved_witness) } -fn read_command() -> Result { +fn step_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, NargoError> { + let mut c = context.lock().unwrap(); + c.show_current_vm_status(); + match c.step_opcode()? { + SolveResult::Done => Ok(Some("Done".to_string())), + SolveResult::Ok => Ok(Some("Ok".to_string())), + } +} + +fn continue_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, NargoError> { + let mut c = context.lock().unwrap(); + c.show_current_vm_status(); + println!("(Continuing execution...)"); loop { - let mut line = String::new(); - print!(">>> "); - io::stdout().flush().unwrap(); - io::stdin().read_line(&mut line)?; - if line.is_empty() { - return Ok(Command::Stop); - } - match line.trim() { - "s" => return Ok(Command::Step), - "c" => return Ok(Command::Continue), - "q" => return Ok(Command::Stop), - "" => continue, - _ => println!("ERROR: unknown command") + match c.step_opcode()? { + SolveResult::Done => break, + SolveResult::Ok => {}, } } + Ok(Some("Ok".to_string())) +} + +fn quit_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, NargoError> { + context.lock().unwrap().show_current_vm_status(); + Err(NargoError::ExecutionError(ExecutionError::Halted)) } diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 03214dec9c3..f3a2fe90b67 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -22,7 +22,6 @@ mod new_cmd; mod prove_cmd; mod test_cmd; mod verify_cmd; -mod debug_cmd; const GIT_HASH: &str = env!("GIT_COMMIT"); const IS_DIRTY: &str = env!("GIT_DIRTY"); From a9804fa71c3b21e2e3be99c98b90042e462674ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 3 Oct 2023 22:39:03 -0400 Subject: [PATCH 05/19] Move all debugger code into a new crate under tooling/debugger --- Cargo.lock | 12 ++++ Cargo.toml | 2 + tooling/debugger/Cargo.toml | 16 ++++++ .../src/ops/debug.rs => debugger/src/lib.rs} | 55 +++++++++++-------- tooling/nargo/src/ops/foreign_calls.rs | 4 +- tooling/nargo/src/ops/mod.rs | 3 +- tooling/nargo_cli/Cargo.toml | 2 +- tooling/nargo_cli/src/cli/debug_cmd.rs | 4 +- tooling/nargo_cli/src/cli/mod.rs | 1 - 9 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 tooling/debugger/Cargo.toml rename tooling/{nargo/src/ops/debug.rs => debugger/src/lib.rs} (84%) diff --git a/Cargo.lock b/Cargo.lock index ac69607c4d2..a6b2511025c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2323,6 +2323,7 @@ dependencies = [ "iter-extended", "nargo", "nargo_toml", + "noir_debugger", "noir_lsp", "noirc_abi", "noirc_driver", @@ -2372,6 +2373,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "noir_debugger" +version = "0.15.0" +dependencies = [ + "acvm", + "nargo", + "noirc_printable_type", + "reedline-repl-rs", + "thiserror", +] + [[package]] name = "noir_lsp" version = "0.16.0" diff --git a/Cargo.toml b/Cargo.toml index 80848fbcf1e..d8896adaa89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ members = [ "tooling/backend_interface", "tooling/bb_abstraction_leaks", "tooling/lsp", + "tooling/debugger", "tooling/nargo", "tooling/nargo_cli", "tooling/nargo_toml", @@ -52,6 +53,7 @@ nargo = { path = "tooling/nargo" } nargo_cli = { path = "tooling/nargo_cli" } nargo_toml = { path = "tooling/nargo_toml" } noir_lsp = { path = "tooling/lsp" } +noir_debugger = { path = "tooling/debugger" } noirc_abi = { path = "tooling/noirc_abi" } bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" } noirc_driver = { path = "compiler/noirc_driver" } diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml new file mode 100644 index 00000000000..319950b526f --- /dev/null +++ b/tooling/debugger/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "noir_debugger" +description = "Debugger for Noir" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +nargo.workspace = true +noirc_printable_type.workspace = true +thiserror.workspace = true +reedline-repl-rs = "1.0.7" diff --git a/tooling/nargo/src/ops/debug.rs b/tooling/debugger/src/lib.rs similarity index 84% rename from tooling/nargo/src/ops/debug.rs rename to tooling/debugger/src/lib.rs index 7630254925e..fdb07ae86bd 100644 --- a/tooling/nargo/src/ops/debug.rs +++ b/tooling/debugger/src/lib.rs @@ -3,15 +3,17 @@ use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; use acvm::acir::circuit::OpcodeLocation; -use crate::artifacts::debug::DebugArtifact; -use crate::errors::ExecutionError; -use crate::NargoError; +use nargo::artifacts::debug::DebugArtifact; +use nargo::errors::ExecutionError; +use nargo::NargoError; -use super::foreign_calls::ForeignCallExecutor; +use nargo::ops::ForeignCallExecutor; use std::rc::Rc; use std::sync::Mutex; +use thiserror::Error; + use reedline_repl_rs::clap::{ ArgMatches as ReplArgMatches, Command as ReplCommand, @@ -23,6 +25,17 @@ enum SolveResult { Ok, } +#[derive(Debug, Error)] +enum DebuggingError { + /// ACIR circuit execution error + #[error(transparent)] + ExecutionError(#[from] nargo::errors::ExecutionError), + + /// Oracle handling error + #[error(transparent)] + ForeignCallError(#[from] noirc_printable_type::ForeignCallError), +} + struct ReplContext<'backend, B: BlackBoxFunctionSolver> { acvm: Option>, debug_artifact: DebugArtifact, @@ -32,7 +45,7 @@ struct ReplContext<'backend, B: BlackBoxFunctionSolver> { } impl<'backend, B> ReplContext<'backend, B> where B: BlackBoxFunctionSolver { - fn step_opcode(&mut self) -> Result { + fn step_opcode(&mut self) -> Result { // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 let assert_messages = &self.circuit.assert_messages; let get_assert_message = |opcode_location| { @@ -59,7 +72,7 @@ impl<'backend, B> ReplContext<'backend, B> where B: BlackBoxFunctionSolver { _ => None, }; - Err(NargoError::ExecutionError(match call_stack { + Err(DebuggingError::ExecutionError(match call_stack { Some(call_stack) => { if let Some(assert_message) = get_assert_message( call_stack.last().expect("Call stacks should not be empty"), @@ -109,22 +122,20 @@ impl<'backend, B> ReplContext<'backend, B> where B: BlackBoxFunctionSolver { } } -impl From for NargoError { +impl From for DebuggingError { fn from(_e: reedline_repl_rs::Error) -> Self { - NargoError::CompilationError + DebuggingError::ExecutionError(ExecutionError::Halted) } } - -// impl fmt::Display for NargoError { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// match self { -// NargoError::CompilationError => write!(f, "Compilation Error"), -// NargoError::ExecutionError(e) => write!(f, "Execution Error: {}", e), -// NargoError::ForeignCallError(e) => write!(f, "Foreign call Error: {}", e), -// } -// } -// } +impl From for DebuggingError { + fn from(e: nargo::errors::NargoError) -> Self { + match e { + NargoError::ForeignCallError(e1) => DebuggingError::ForeignCallError(e1), + _ => DebuggingError::ExecutionError(ExecutionError::Halted), + } + } +} pub fn debug_circuit( blackbox_solver: &B, @@ -167,7 +178,7 @@ pub fn debug_circuit( Ok(solved_witness) } -fn step_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, NargoError> { +fn step_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, DebuggingError> { let mut c = context.lock().unwrap(); c.show_current_vm_status(); match c.step_opcode()? { @@ -176,7 +187,7 @@ fn step_command(_args: ReplArgMatches, context: &mut } } -fn continue_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, NargoError> { +fn continue_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, DebuggingError> { let mut c = context.lock().unwrap(); c.show_current_vm_status(); println!("(Continuing execution...)"); @@ -189,7 +200,7 @@ fn continue_command(_args: ReplArgMatches, context: & Ok(Some("Ok".to_string())) } -fn quit_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, NargoError> { +fn quit_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, DebuggingError> { context.lock().unwrap().show_current_vm_status(); - Err(NargoError::ExecutionError(ExecutionError::Halted)) + Err(DebuggingError::ExecutionError(ExecutionError::Halted)) } diff --git a/tooling/nargo/src/ops/foreign_calls.rs b/tooling/nargo/src/ops/foreign_calls.rs index e44ab1732c9..4d20a0bd4f0 100644 --- a/tooling/nargo/src/ops/foreign_calls.rs +++ b/tooling/nargo/src/ops/foreign_calls.rs @@ -89,7 +89,7 @@ impl MockedCall { } #[derive(Debug, Default)] -pub(crate) struct ForeignCallExecutor { +pub struct ForeignCallExecutor { /// Mocks have unique ids used to identify them in Noir, allowing to update or remove them. last_mock_id: usize, /// The registered mocks @@ -97,7 +97,7 @@ pub(crate) struct ForeignCallExecutor { } impl ForeignCallExecutor { - pub(crate) fn execute( + pub fn execute( &mut self, foreign_call: &ForeignCallWaitInfo, show_output: bool, diff --git a/tooling/nargo/src/ops/mod.rs b/tooling/nargo/src/ops/mod.rs index 16933a8217c..ab0aaf6c37d 100644 --- a/tooling/nargo/src/ops/mod.rs +++ b/tooling/nargo/src/ops/mod.rs @@ -1,10 +1,9 @@ pub use self::execute::execute_circuit; -pub use self::debug::debug_circuit; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::test::{run_test, TestStatus}; +pub use self::foreign_calls::ForeignCallExecutor; mod execute; -mod debug; mod foreign_calls; mod optimize; mod test; diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index bd9f14b035c..9bb37f6429c 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -25,6 +25,7 @@ iter-extended.workspace = true nargo.workspace = true nargo_toml.workspace = true noir_lsp.workspace = true +noir_debugger.workspace = true noirc_driver.workspace = true noirc_frontend.workspace = true noirc_abi.workspace = true @@ -36,7 +37,6 @@ serde.workspace = true serde_json.workspace = true prettytable-rs = "0.10" rayon = "1.7.0" -reedline-repl-rs = "1.0.7" thiserror.workspace = true tower.workspace = true async-lsp = { version = "0.0.5", default-features = false, features = [ diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 8740860c172..db1b75428c5 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -10,6 +10,8 @@ use noirc_abi::InputMap; use noirc_driver::{CompileOptions, CompiledProgram}; use noirc_frontend::graph::CrateName; +use noir_debugger; + use super::compile_cmd::compile_bin_package; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; use super::NargoConfig; @@ -105,7 +107,7 @@ pub(crate) fn debug_program( file_map: compiled_program.file_map.clone(), }; - let solved_witness_err = nargo::ops::debug_circuit( + let solved_witness_err = noir_debugger::debug_circuit( &blackbox_solver, compiled_program.circuit.clone(), debug_artifact, diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index f3a2fe90b67..0324c7e8848 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -96,7 +96,6 @@ pub(crate) fn start_cli() -> eyre::Result<()> { NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config), - NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config), NargoCommand::Verify(args) => verify_cmd::run(&backend, args, config), NargoCommand::Test(args) => test_cmd::run(&backend, args, config), From 67c56151be20dc59198504d718a24e330f7ac2ed Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Wed, 4 Oct 2023 12:48:51 +0200 Subject: [PATCH 06/19] Cargo.lock update --- Cargo.lock | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6b2511025c..5d02c852f72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,8 +15,8 @@ dependencies = [ "serde-generate", "serde-reflection", "serde_json", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.3", "thiserror", ] @@ -350,6 +350,12 @@ dependencies = [ "rand", ] +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "arrayvec" version = "0.7.4" @@ -960,7 +966,7 @@ version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ - "arrayvec", + "arrayvec 0.7.4", "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", @@ -1116,6 +1122,32 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossterm" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "serde", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -1456,6 +1488,17 @@ dependencies = [ "instant", ] +[[package]] +name = "fd-lock" +version = "3.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" +dependencies = [ + "cfg-if", + "rustix 0.38.4", + "windows-sys 0.48.0", +] + [[package]] name = "ff" version = "0.12.1" @@ -2270,6 +2313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -2375,7 +2419,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.15.0" +version = "0.16.0" dependencies = [ "acvm", "nargo", @@ -2439,8 +2483,8 @@ dependencies = [ "num-traits", "serde", "serde_json", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.3", "thiserror", "toml", ] @@ -2522,8 +2566,8 @@ dependencies = [ "serde_json", "small-ord-set", "smol_str", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.3", "thiserror", ] @@ -2545,6 +2589,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "nu-ansi-term" +version = "0.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -2562,7 +2615,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec", + "arrayvec 0.7.4", "itoa", ] @@ -3061,6 +3114,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "reedline" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fde955d11817fdcb79d703932fb6b473192cb36b6a92ba21f7f4ac0513374e" +dependencies = [ + "chrono", + "crossterm", + "fd-lock", + "itertools", + "nu-ansi-term", + "serde", + "strip-ansi-escapes", + "strum 0.25.0", + "strum_macros 0.25.2", + "thiserror", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "reedline-repl-rs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dda59601d3b0c3ed9de96d342ca40f95cca2409e8497249139a6c723b211ee33" +dependencies = [ + "clap", + "crossterm", + "nu-ansi-term", + "reedline", + "regex", + "winapi-util", + "yansi", +] + [[package]] name = "regalloc2" version = "0.5.1" @@ -3651,6 +3739,36 @@ dependencies = [ "dirs", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "1.6.4" @@ -3772,6 +3890,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" +[[package]] +name = "strip-ansi-escapes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.10.0" @@ -3784,6 +3911,12 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + [[package]] name = "strum_macros" version = "0.24.3" @@ -3797,6 +3930,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.26", +] + [[package]] name = "subtle" version = "2.5.0" @@ -4282,6 +4428,27 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vte" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" +dependencies = [ + "arrayvec 0.5.2", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "wait-timeout" version = "0.2.0" @@ -4827,6 +4994,12 @@ dependencies = [ "libc", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "zeroize" version = "1.6.0" From 8a61999bd2fc580ab3abda01eecd96a227ec5342 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Wed, 4 Oct 2023 17:55:38 +0200 Subject: [PATCH 07/19] Port repl to easy-repl (not compiling) --- Cargo.lock | 178 +++++++++++++++++++++++++- tooling/debugger/Cargo.toml | 1 + tooling/debugger/src/lib.rs | 245 +++++++++++++++++++----------------- 3 files changed, 304 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d02c852f72..96ab6106e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -807,6 +807,17 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "codespan" version = "0.11.1" @@ -1342,6 +1353,21 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "easy-repl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d0001ed25c451c57f8d6724d448a6546a5d78bbac77a63a22e32c735b7ea16" +dependencies = [ + "anyhow", + "rustyline", + "rustyline-derive", + "shell-words", + "textwrap 0.15.2", + "thiserror", + "trie-rs", +] + [[package]] name = "ecdsa" version = "0.14.8" @@ -1395,6 +1421,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + [[package]] name = "enum-iterator" version = "0.7.0" @@ -1463,6 +1495,16 @@ dependencies = [ "libc", ] +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "eyre" version = "0.6.8" @@ -1509,6 +1551,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "fid-rs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28658c0c3420305705adde833a0d2d614207507d013a5f25707553fb2ae2cd" +dependencies = [ + "rayon", +] + [[package]] name = "filetime" version = "0.2.22" @@ -2223,6 +2274,15 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "louds-rs" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16a91fb20f74b6d9a758a0103a2884af525a2fa34fbfe19f4b3c5482a4a54e9" +dependencies = [ + "fid-rs", +] + [[package]] name = "lsp-types" version = "0.88.0" @@ -2273,6 +2333,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.8.0" @@ -2405,6 +2474,28 @@ dependencies = [ "url", ] +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.26.2" @@ -2422,6 +2513,7 @@ name = "noir_debugger" version = "0.16.0" dependencies = [ "acvm", + "easy-repl", "nargo", "noirc_printable_type", "reedline-repl-rs", @@ -2835,7 +2927,7 @@ dependencies = [ "inferno", "libc", "log", - "nix", + "nix 0.26.2", "once_cell", "parking_lot", "smallvec", @@ -3015,6 +3107,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "rand" version = "0.8.5" @@ -3453,6 +3555,40 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "rustyline" +version = "9.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "clipboard-win", + "dirs-next", + "fd-lock", + "libc", + "log", + "memchr", + "nix 0.23.2", + "radix_trie", + "scopeguard", + "smallvec", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + +[[package]] +name = "rustyline-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb35a55ab810b5c0fe31606fe9b47d1354e4dc519bec0a102655f78ea2b38057" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ryu" version = "1.0.15" @@ -3592,7 +3728,7 @@ dependencies = [ "phf", "serde", "serde-reflection", - "textwrap", + "textwrap 0.13.4", ] [[package]] @@ -3730,6 +3866,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shellexpand" version = "2.1.2" @@ -3884,6 +4026,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "str_stack" version = "0.1.0" @@ -4080,6 +4228,17 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.43" @@ -4329,6 +4488,15 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "trie-rs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5096c019d49566aff57593a06e401c7f588da84e9a575d0ed2ac0913f51928c0" +dependencies = [ + "louds-rs", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -4359,6 +4527,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.22" diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index 319950b526f..f488831609c 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -14,3 +14,4 @@ nargo.workspace = true noirc_printable_type.workspace = true thiserror.workspace = true reedline-repl-rs = "1.0.7" +easy-repl = "0.2.1" \ No newline at end of file diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index fdb07ae86bd..c8a9430453f 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -9,16 +9,15 @@ use nargo::NargoError; use nargo::ops::ForeignCallExecutor; -use std::rc::Rc; -use std::sync::Mutex; - use thiserror::Error; -use reedline_repl_rs::clap::{ - ArgMatches as ReplArgMatches, - Command as ReplCommand, -}; -use reedline_repl_rs::Repl; +use easy_repl::{Repl, CommandStatus, command}; + +// use reedline_repl_rs::clap::{ +// ArgMatches as ReplArgMatches, +// Command as ReplCommand, +// }; +// use reedline_repl_rs::Repl; enum SolveResult { Done, @@ -44,84 +43,78 @@ struct ReplContext<'backend, B: BlackBoxFunctionSolver> { show_output: bool, } -impl<'backend, B> ReplContext<'backend, B> where B: BlackBoxFunctionSolver { - fn step_opcode(&mut self) -> Result { - // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 - let assert_messages = &self.circuit.assert_messages; - let get_assert_message = |opcode_location| { - assert_messages - .iter() - .find(|(loc, _)| loc == opcode_location) - .map(|(_, message)| message.clone()) - }; - - let acvm = self.acvm.as_mut().unwrap(); - let solver_status = acvm.solve_opcode(); - - match solver_status { - ACVMStatus::Solved => Ok(SolveResult::Done), - ACVMStatus::InProgress => Ok(SolveResult::Ok), - ACVMStatus::Failure(error) => { - let call_stack = match &error { - OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Resolved(opcode_location), - } => Some(vec![*opcode_location]), - OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - Some(call_stack.clone()) - } - _ => None, - }; - - Err(DebuggingError::ExecutionError(match call_stack { - Some(call_stack) => { - if let Some(assert_message) = get_assert_message( - call_stack.last().expect("Call stacks should not be empty"), - ) { - ExecutionError::AssertionFailed(assert_message, call_stack) - } else { - ExecutionError::SolvingError(error) - } +fn step_opcode<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, circuit: Circuit, foreign_call_executor: &mut ForeignCallExecutor, show_output: bool) -> Result { + // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 + let assert_messages = circuit.assert_messages; + let get_assert_message = |opcode_location| { + assert_messages + .iter() + .find(|(loc, _)| loc == opcode_location) + .map(|(_, message)| message.clone()) + }; + + // let acvm = self.acvm.as_mut().unwrap(); + let solver_status = acvm.solve_opcode(); + + match solver_status { + ACVMStatus::Solved => Ok(SolveResult::Done), + ACVMStatus::InProgress => Ok(SolveResult::Ok), + ACVMStatus::Failure(error) => { + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + } => Some(vec![*opcode_location]), + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + Some(call_stack.clone()) + } + _ => None, + }; + + Err(DebuggingError::ExecutionError(match call_stack { + Some(call_stack) => { + if let Some(assert_message) = get_assert_message( + call_stack.last().expect("Call stacks should not be empty"), + ) { + ExecutionError::AssertionFailed(assert_message, call_stack) + } else { + ExecutionError::SolvingError(error) } - None => ExecutionError::SolvingError(error), - })) - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = self.foreign_call_executor.execute(&foreign_call, self.show_output)?; - acvm.resolve_pending_foreign_call(foreign_call_result); - Ok(SolveResult::Ok) - } - } - } - - fn show_current_vm_status(&self) { - let acvm = self.acvm.as_ref().unwrap(); - let ip = acvm.instruction_pointer(); - println!("Stopped at opcode {}: {}", ip, acvm.opcodes()[ip]); - self.show_source_code_location(&OpcodeLocation::Acir(ip)); - } - - fn show_source_code_location(&self, location: &OpcodeLocation) { - let locations = self.debug_artifact.debug_symbols[0].opcode_location(&location); - match locations { - Some(locations) => { - for loc in locations { - let file = &self.debug_artifact.file_map[&loc.file]; - let source = &file.source.as_str(); - let start = loc.span.start() as usize; - let end = loc.span.end() as usize; - println!("At {}:{start}-{end}", file.path.as_path().display()); - println!("\n{}\n", &source[start..end]); } - }, - None => {} + None => ExecutionError::SolvingError(error), + })) + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let foreign_call_result = foreign_call_executor.execute(&foreign_call, show_output)?; + acvm.resolve_pending_foreign_call(foreign_call_result); + Ok(SolveResult::Ok) } } +} + +fn show_current_vm_status<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact) { + let ip = acvm.instruction_pointer(); + println!("Stopped at opcode {}: {}", ip, acvm.opcodes()[ip]); + show_source_code_location(&OpcodeLocation::Acir(ip), debug_artifact); +} - fn finalize(&mut self) -> WitnessMap { - self.acvm.take().unwrap().finalize() +fn show_source_code_location(location: &OpcodeLocation, debug_artifact: DebugArtifact) { + let locations = debug_artifact.debug_symbols[0].opcode_location(&location); + match locations { + Some(locations) => { + for loc in locations { + let file = &debug_artifact.file_map[&loc.file]; + let source = &file.source.as_str(); + let start = loc.span.start() as usize; + let end = loc.span.end() as usize; + println!("At {}:{start}-{end}", file.path.as_path().display()); + println!("\n{}\n", &source[start..end]); + } + }, + None => {} } } + impl From for DebuggingError { fn from(_e: reedline_repl_rs::Error) -> Self { DebuggingError::ExecutionError(ExecutionError::Halted) @@ -145,54 +138,70 @@ pub fn debug_circuit( show_output: bool, ) -> Result { let opcodes = circuit.opcodes.clone(); - let acvm = ACVM::new(blackbox_solver, opcodes, initial_witness); - let foreign_call_executor = ForeignCallExecutor::default(); - - let repl_context = Rc::new(Mutex::new(ReplContext { - acvm: Some(acvm), - debug_artifact, - foreign_call_executor, - circuit, - show_output, - })); - let mut repl = Repl::new(repl_context.clone()) - .with_name("debug") - .with_version(env!["CARGO_PKG_VERSION"]) - .with_command( - ReplCommand::new("s") - .about("step to the next opcode"), - step_command, - ) - .with_command( - ReplCommand::new("c") - .about("continue execution until the end of the program"), - continue_command, - ) - .with_command( - ReplCommand::new("q") - .about("quit the debugger"), - quit_command, - ); - repl.run().unwrap(); - let solved_witness = repl_context.lock().unwrap().finalize(); + let mut acvm = ACVM::new(blackbox_solver, opcodes, initial_witness); + let mut foreign_call_executor = ForeignCallExecutor::default(); + + let mut repl = Repl::builder() + .add("s", command! { + "step to the next opcode", + () => || { + step_command(&mut acvm, debug_artifact, circuit, &mut foreign_call_executor, show_output); + Ok(CommandStatus::Done) + } + }) + .add("c", command! { + "continue execution until the end of the program", + () => || { + continue_command(&mut acvm, debug_artifact, circuit, &mut foreign_call_executor, show_output); + Ok(CommandStatus::Quit) + } + }) + .add("q", command! { + "quit the debugger", + () => || { + quit_command(&mut acvm, debug_artifact); + Ok(CommandStatus::Quit) + } + }).build().expect("Failed to initialize debugger repl"); + repl.run().expect("Critical debugger error"); + + // // let mut repl = Repl::new(repl_context.clone()) + // // .with_name("debug") + // // .with_version(env!["CARGO_PKG_VERSION"]) + // // .with_command( + // // ReplCommand::new("s") + // // .about("step to the next opcode"), + // // step_command, + // // ) + // // .with_command( + // // ReplCommand::new("c") + // // .about("continue execution until the end of the program"), + // // continue_command, + // // ) + // // .with_command( + // // ReplCommand::new("q") + // // .about("quit the debugger"), + // // quit_command, + // // ); + // // repl.run().unwrap(); + + let solved_witness = acvm.finalize(); Ok(solved_witness) } -fn step_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, DebuggingError> { - let mut c = context.lock().unwrap(); - c.show_current_vm_status(); - match c.step_opcode()? { +fn step_command<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact, circuit: Circuit, foreign_call_executor: &mut ForeignCallExecutor, show_output: bool) -> Result, DebuggingError> { + show_current_vm_status(acvm, debug_artifact); + match step_opcode(acvm, circuit, foreign_call_executor, show_output)? { SolveResult::Done => Ok(Some("Done".to_string())), SolveResult::Ok => Ok(Some("Ok".to_string())), } } -fn continue_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, DebuggingError> { - let mut c = context.lock().unwrap(); - c.show_current_vm_status(); +fn continue_command<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact, circuit: Circuit, foreign_call_executor: &mut ForeignCallExecutor, show_output: bool) -> Result, DebuggingError> { + show_current_vm_status(acvm, debug_artifact); println!("(Continuing execution...)"); loop { - match c.step_opcode()? { + match step_opcode(acvm, circuit, foreign_call_executor, show_output)? { SolveResult::Done => break, SolveResult::Ok => {}, } @@ -200,7 +209,7 @@ fn continue_command(_args: ReplArgMatches, context: & Ok(Some("Ok".to_string())) } -fn quit_command(_args: ReplArgMatches, context: &mut Rc>>) -> Result, DebuggingError> { - context.lock().unwrap().show_current_vm_status(); +fn quit_command<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact) -> Result, DebuggingError> { + show_current_vm_status(acvm, debug_artifact); Err(DebuggingError::ExecutionError(ExecutionError::Halted)) } From 43fecdae3e37e432a9734f2256ebd274c9a08799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 5 Oct 2023 04:47:21 -0400 Subject: [PATCH 08/19] Fix compilation with easy-repl --- Cargo.lock | 179 ++----------------------- tooling/debugger/Cargo.toml | 1 - tooling/debugger/src/lib.rs | 256 +++++++++++++++++------------------- 3 files changed, 128 insertions(+), 308 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96ab6106e0f..1612acddce9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,8 +15,8 @@ dependencies = [ "serde-generate", "serde-reflection", "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", + "strum", + "strum_macros", "thiserror", ] @@ -350,12 +350,6 @@ dependencies = [ "rand", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.4" @@ -977,7 +971,7 @@ version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", @@ -1133,32 +1127,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossterm" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" -dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio", - "parking_lot", - "serde", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - [[package]] name = "crypto-bigint" version = "0.4.9" @@ -2382,7 +2350,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.48.0", ] @@ -2516,7 +2483,6 @@ dependencies = [ "easy-repl", "nargo", "noirc_printable_type", - "reedline-repl-rs", "thiserror", ] @@ -2575,8 +2541,8 @@ dependencies = [ "num-traits", "serde", "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", + "strum", + "strum_macros", "thiserror", "toml", ] @@ -2658,8 +2624,8 @@ dependencies = [ "serde_json", "small-ord-set", "smol_str", - "strum 0.24.1", - "strum_macros 0.24.3", + "strum", + "strum_macros", "thiserror", ] @@ -2681,15 +2647,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" -[[package]] -name = "nu-ansi-term" -version = "0.49.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" -dependencies = [ - "windows-sys 0.48.0", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -2707,7 +2664,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "itoa", ] @@ -3216,41 +3173,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "reedline" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fde955d11817fdcb79d703932fb6b473192cb36b6a92ba21f7f4ac0513374e" -dependencies = [ - "chrono", - "crossterm", - "fd-lock", - "itertools", - "nu-ansi-term", - "serde", - "strip-ansi-escapes", - "strum 0.25.0", - "strum_macros 0.25.2", - "thiserror", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "reedline-repl-rs" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda59601d3b0c3ed9de96d342ca40f95cca2409e8497249139a6c723b211ee33" -dependencies = [ - "clap", - "crossterm", - "nu-ansi-term", - "reedline", - "regex", - "winapi-util", - "yansi", -] - [[package]] name = "regalloc2" version = "0.5.1" @@ -3881,36 +3803,6 @@ dependencies = [ "dirs", ] -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - [[package]] name = "signature" version = "1.6.4" @@ -4038,15 +3930,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" -[[package]] -name = "strip-ansi-escapes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" -dependencies = [ - "vte", -] - [[package]] name = "strsim" version = "0.10.0" @@ -4059,12 +3942,6 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" - [[package]] name = "strum_macros" version = "0.24.3" @@ -4078,19 +3955,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "strum_macros" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.26", -] - [[package]] name = "subtle" version = "2.5.0" @@ -4602,27 +4466,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "vte" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" -dependencies = [ - "arrayvec 0.5.2", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" -dependencies = [ - "proc-macro2", - "quote", -] - [[package]] name = "wait-timeout" version = "0.2.0" @@ -5168,12 +5011,6 @@ dependencies = [ "libc", ] -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - [[package]] name = "zeroize" version = "1.6.0" diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index f488831609c..5b8248345a0 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -13,5 +13,4 @@ acvm.workspace = true nargo.workspace = true noirc_printable_type.workspace = true thiserror.workspace = true -reedline-repl-rs = "1.0.7" easy-repl = "0.2.1" \ No newline at end of file diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index c8a9430453f..5534861a463 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -11,13 +11,8 @@ use nargo::ops::ForeignCallExecutor; use thiserror::Error; -use easy_repl::{Repl, CommandStatus, command}; - -// use reedline_repl_rs::clap::{ -// ArgMatches as ReplArgMatches, -// Command as ReplCommand, -// }; -// use reedline_repl_rs::Repl; +use easy_repl::{Repl, CommandStatus, command, Critical}; +use std::cell::RefCell; enum SolveResult { Done, @@ -35,7 +30,7 @@ enum DebuggingError { ForeignCallError(#[from] noirc_printable_type::ForeignCallError), } -struct ReplContext<'backend, B: BlackBoxFunctionSolver> { +struct DebugContext<'backend, B: BlackBoxFunctionSolver> { acvm: Option>, debug_artifact: DebugArtifact, foreign_call_executor: ForeignCallExecutor, @@ -43,81 +38,85 @@ struct ReplContext<'backend, B: BlackBoxFunctionSolver> { show_output: bool, } -fn step_opcode<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, circuit: Circuit, foreign_call_executor: &mut ForeignCallExecutor, show_output: bool) -> Result { - // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 - let assert_messages = circuit.assert_messages; - let get_assert_message = |opcode_location| { - assert_messages - .iter() - .find(|(loc, _)| loc == opcode_location) - .map(|(_, message)| message.clone()) - }; - - // let acvm = self.acvm.as_mut().unwrap(); - let solver_status = acvm.solve_opcode(); - - match solver_status { - ACVMStatus::Solved => Ok(SolveResult::Done), - ACVMStatus::InProgress => Ok(SolveResult::Ok), - ACVMStatus::Failure(error) => { - let call_stack = match &error { - OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Resolved(opcode_location), - } => Some(vec![*opcode_location]), - OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - Some(call_stack.clone()) - } - _ => None, - }; - - Err(DebuggingError::ExecutionError(match call_stack { - Some(call_stack) => { - if let Some(assert_message) = get_assert_message( - call_stack.last().expect("Call stacks should not be empty"), - ) { - ExecutionError::AssertionFailed(assert_message, call_stack) - } else { - ExecutionError::SolvingError(error) +impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { + fn step_opcode(&mut self) -> Result { + // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 + let assert_messages = &self.circuit.assert_messages; + let get_assert_message = |opcode_location| { + assert_messages + .iter() + .find(|(loc, _)| loc == opcode_location) + .map(|(_, message)| message.clone()) + }; + + let solver_status = self.acvm.as_mut().unwrap().solve_opcode(); + + match solver_status { + ACVMStatus::Solved => Ok(SolveResult::Done), + ACVMStatus::InProgress => Ok(SolveResult::Ok), + ACVMStatus::Failure(error) => { + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + } => Some(vec![*opcode_location]), + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + Some(call_stack.clone()) } - } - None => ExecutionError::SolvingError(error), - })) - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = foreign_call_executor.execute(&foreign_call, show_output)?; - acvm.resolve_pending_foreign_call(foreign_call_result); - Ok(SolveResult::Ok) + _ => None, + }; + + Err(DebuggingError::ExecutionError(match call_stack { + Some(call_stack) => { + if let Some(assert_message) = get_assert_message( + call_stack.last().expect("Call stacks should not be empty"), + ) { + ExecutionError::AssertionFailed(assert_message, call_stack) + } else { + ExecutionError::SolvingError(error) + } + } + None => ExecutionError::SolvingError(error), + })) + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let foreign_call_result = self.foreign_call_executor.execute(&foreign_call, self.show_output)?; + self.acvm.as_mut().unwrap().resolve_pending_foreign_call(foreign_call_result); + Ok(SolveResult::Ok) + } } } -} - -fn show_current_vm_status<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact) { - let ip = acvm.instruction_pointer(); - println!("Stopped at opcode {}: {}", ip, acvm.opcodes()[ip]); - show_source_code_location(&OpcodeLocation::Acir(ip), debug_artifact); -} -fn show_source_code_location(location: &OpcodeLocation, debug_artifact: DebugArtifact) { - let locations = debug_artifact.debug_symbols[0].opcode_location(&location); - match locations { - Some(locations) => { - for loc in locations { - let file = &debug_artifact.file_map[&loc.file]; - let source = &file.source.as_str(); - let start = loc.span.start() as usize; - let end = loc.span.end() as usize; - println!("At {}:{start}-{end}", file.path.as_path().display()); - println!("\n{}\n", &source[start..end]); - } - }, - None => {} + fn show_current_vm_status(&self) { + let ip = self.acvm.as_ref().unwrap().instruction_pointer(); + println!("Stopped at opcode {}: {}", ip, self.acvm.as_ref().unwrap().opcodes()[ip]); + Self::show_source_code_location(&OpcodeLocation::Acir(ip), &self.debug_artifact); } -} + fn show_source_code_location(location: &OpcodeLocation, debug_artifact: &DebugArtifact) { + let locations = debug_artifact.debug_symbols[0].opcode_location(&location); + match locations { + Some(locations) => { + for loc in locations { + let file = &debug_artifact.file_map[&loc.file]; + let source = &file.source.as_str(); + let start = loc.span.start() as usize; + let end = loc.span.end() as usize; + println!("At {}:{start}-{end}", file.path.as_path().display()); + println!("\n{}\n", &source[start..end]); + } + }, + None => {} + } + } -impl From for DebuggingError { - fn from(_e: reedline_repl_rs::Error) -> Self { - DebuggingError::ExecutionError(ExecutionError::Halted) + fn cont(&mut self) -> Result { + loop { + match self.step_opcode()? { + SolveResult::Done => break, + SolveResult::Ok => {}, + } + } + Ok(SolveResult::Done) } } @@ -130,6 +129,13 @@ impl From for DebuggingError { } } +fn map_command_status(result: SolveResult) -> CommandStatus { + match result { + SolveResult::Ok => CommandStatus::Done, + SolveResult::Done => CommandStatus::Quit + } +} + pub fn debug_circuit( blackbox_solver: &B, circuit: Circuit, @@ -138,78 +144,56 @@ pub fn debug_circuit( show_output: bool, ) -> Result { let opcodes = circuit.opcodes.clone(); - let mut acvm = ACVM::new(blackbox_solver, opcodes, initial_witness); - let mut foreign_call_executor = ForeignCallExecutor::default(); + + let context = RefCell::new(DebugContext { + acvm: Some(ACVM::new(blackbox_solver, opcodes, initial_witness)), + foreign_call_executor: ForeignCallExecutor::default(), + circuit, + debug_artifact, + show_output, + }); + let ref_step = &context; + let ref_cont = &context; + + let solved = RefCell::new(false); + + context.borrow().show_current_vm_status(); + + let handle_result = |result| { + solved.replace(match result { + SolveResult::Done => true, + _ => false, + }); + Ok(map_command_status(result)) + }; let mut repl = Repl::builder() .add("s", command! { "step to the next opcode", () => || { - step_command(&mut acvm, debug_artifact, circuit, &mut foreign_call_executor, show_output); - Ok(CommandStatus::Done) - } + let result = ref_step.borrow_mut().step_opcode().into_critical()?; + ref_step.borrow().show_current_vm_status(); + handle_result(result) + } }) .add("c", command! { "continue execution until the end of the program", () => || { - continue_command(&mut acvm, debug_artifact, circuit, &mut foreign_call_executor, show_output); - Ok(CommandStatus::Quit) + println!("(Continuing execution...)"); + let result = ref_cont.borrow_mut().cont().into_critical()?; + handle_result(result) } }) - .add("q", command! { - "quit the debugger", - () => || { - quit_command(&mut acvm, debug_artifact); - Ok(CommandStatus::Quit) - } - }).build().expect("Failed to initialize debugger repl"); - repl.run().expect("Critical debugger error"); - - // // let mut repl = Repl::new(repl_context.clone()) - // // .with_name("debug") - // // .with_version(env!["CARGO_PKG_VERSION"]) - // // .with_command( - // // ReplCommand::new("s") - // // .about("step to the next opcode"), - // // step_command, - // // ) - // // .with_command( - // // ReplCommand::new("c") - // // .about("continue execution until the end of the program"), - // // continue_command, - // // ) - // // .with_command( - // // ReplCommand::new("q") - // // .about("quit the debugger"), - // // quit_command, - // // ); - // // repl.run().unwrap(); - - let solved_witness = acvm.finalize(); - Ok(solved_witness) -} + .build() + .expect("Failed to initialize debugger repl"); -fn step_command<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact, circuit: Circuit, foreign_call_executor: &mut ForeignCallExecutor, show_output: bool) -> Result, DebuggingError> { - show_current_vm_status(acvm, debug_artifact); - match step_opcode(acvm, circuit, foreign_call_executor, show_output)? { - SolveResult::Done => Ok(Some("Done".to_string())), - SolveResult::Ok => Ok(Some("Ok".to_string())), - } -} + repl.run().expect("Debugger error"); -fn continue_command<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact, circuit: Circuit, foreign_call_executor: &mut ForeignCallExecutor, show_output: bool) -> Result, DebuggingError> { - show_current_vm_status(acvm, debug_artifact); - println!("(Continuing execution...)"); - loop { - match step_opcode(acvm, circuit, foreign_call_executor, show_output)? { - SolveResult::Done => break, - SolveResult::Ok => {}, - } + let acvm = context.borrow_mut().acvm.take().unwrap(); + if *solved.borrow() { + let solved_witness = acvm.finalize(); + Ok(solved_witness) + } else { + Err(NargoError::ExecutionError(ExecutionError::Halted)) } - Ok(Some("Ok".to_string())) -} - -fn quit_command<'backend, B: BlackBoxFunctionSolver>(acvm: &mut ACVM<'backend, B>, debug_artifact: DebugArtifact) -> Result, DebuggingError> { - show_current_vm_status(acvm, debug_artifact); - Err(DebuggingError::ExecutionError(ExecutionError::Halted)) } From c176f77df7b82639b4a191258b56308d002c4045 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 5 Oct 2023 15:12:18 +0200 Subject: [PATCH 09/19] Format --- tooling/debugger/src/lib.rs | 51 +++++++++++++++----------- tooling/nargo/src/ops/mod.rs | 2 +- tooling/nargo_cli/src/cli/debug_cmd.rs | 6 +-- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 5534861a463..d6b0147b34f 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -1,7 +1,7 @@ +use acvm::acir::circuit::OpcodeLocation; use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}; use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; -use acvm::acir::circuit::OpcodeLocation; use nargo::artifacts::debug::DebugArtifact; use nargo::errors::ExecutionError; @@ -11,7 +11,7 @@ use nargo::ops::ForeignCallExecutor; use thiserror::Error; -use easy_repl::{Repl, CommandStatus, command, Critical}; +use easy_repl::{command, CommandStatus, Critical, Repl}; use std::cell::RefCell; enum SolveResult { @@ -79,7 +79,8 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { })) } ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = self.foreign_call_executor.execute(&foreign_call, self.show_output)?; + let foreign_call_result = + self.foreign_call_executor.execute(&foreign_call, self.show_output)?; self.acvm.as_mut().unwrap().resolve_pending_foreign_call(foreign_call_result); Ok(SolveResult::Ok) } @@ -104,7 +105,7 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { println!("At {}:{start}-{end}", file.path.as_path().display()); println!("\n{}\n", &source[start..end]); } - }, + } None => {} } } @@ -113,7 +114,7 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { loop { match self.step_opcode()? { SolveResult::Done => break, - SolveResult::Ok => {}, + SolveResult::Ok => {} } } Ok(SolveResult::Done) @@ -132,7 +133,7 @@ impl From for DebuggingError { fn map_command_status(result: SolveResult) -> CommandStatus { match result { SolveResult::Ok => CommandStatus::Done, - SolveResult::Done => CommandStatus::Quit + SolveResult::Done => CommandStatus::Quit, } } @@ -168,22 +169,28 @@ pub fn debug_circuit( }; let mut repl = Repl::builder() - .add("s", command! { - "step to the next opcode", - () => || { - let result = ref_step.borrow_mut().step_opcode().into_critical()?; - ref_step.borrow().show_current_vm_status(); - handle_result(result) - } - }) - .add("c", command! { - "continue execution until the end of the program", - () => || { - println!("(Continuing execution...)"); - let result = ref_cont.borrow_mut().cont().into_critical()?; - handle_result(result) - } - }) + .add( + "s", + command! { + "step to the next opcode", + () => || { + let result = ref_step.borrow_mut().step_opcode().into_critical()?; + ref_step.borrow().show_current_vm_status(); + handle_result(result) + } + }, + ) + .add( + "c", + command! { + "continue execution until the end of the program", + () => || { + println!("(Continuing execution...)"); + let result = ref_cont.borrow_mut().cont().into_critical()?; + handle_result(result) + } + }, + ) .build() .expect("Failed to initialize debugger repl"); diff --git a/tooling/nargo/src/ops/mod.rs b/tooling/nargo/src/ops/mod.rs index ab0aaf6c37d..491320482cf 100644 --- a/tooling/nargo/src/ops/mod.rs +++ b/tooling/nargo/src/ops/mod.rs @@ -1,7 +1,7 @@ pub use self::execute::execute_circuit; +pub use self::foreign_calls::ForeignCallExecutor; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::test::{run_test, TestStatus}; -pub use self::foreign_calls::ForeignCallExecutor; mod execute; mod foreign_calls; diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index db1b75428c5..5f457d9fe2d 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -1,9 +1,9 @@ use acvm::acir::native_types::WitnessMap; use clap::Args; +use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; use nargo::package::Package; -use nargo::artifacts::debug::DebugArtifact; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; @@ -116,8 +116,6 @@ pub(crate) fn debug_program( ); match solved_witness_err { Ok(solved_witness) => Ok(solved_witness), - Err(err) => { - Err(crate::errors::CliError::NargoError(err)) - } + Err(err) => Err(crate::errors::CliError::NargoError(err)), } } From da1657e2546984385aa7bd3f41bbdee090507bab Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 5 Oct 2023 15:24:50 +0200 Subject: [PATCH 10/19] Update tooling/nargo_cli/src/cli/mod.rs Co-authored-by: kevaundray --- tooling/nargo_cli/src/cli/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 0324c7e8848..f864b2284f7 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -59,6 +59,7 @@ enum NargoCommand { New(new_cmd::NewCommand), Init(init_cmd::InitCommand), Execute(execute_cmd::ExecuteCommand), + #[command(hide = true)] // Hidden while the feature is being built out Debug(debug_cmd::DebugCommand), Prove(prove_cmd::ProveCommand), Verify(verify_cmd::VerifyCommand), From f0717e3519d63185280202e3e0ebc2f5444c82c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 5 Oct 2023 21:53:12 -0400 Subject: [PATCH 11/19] Fix panic when trying to show status and the execution finished Also use a Cell (instead of a RefCell) to store the solved status. --- tooling/debugger/src/lib.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index d6b0147b34f..306b8c7f301 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -12,7 +12,7 @@ use nargo::ops::ForeignCallExecutor; use thiserror::Error; use easy_repl::{command, CommandStatus, Critical, Repl}; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; enum SolveResult { Done, @@ -88,9 +88,15 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { } fn show_current_vm_status(&self) { - let ip = self.acvm.as_ref().unwrap().instruction_pointer(); - println!("Stopped at opcode {}: {}", ip, self.acvm.as_ref().unwrap().opcodes()[ip]); - Self::show_source_code_location(&OpcodeLocation::Acir(ip), &self.debug_artifact); + let acvm = self.acvm.as_ref().unwrap(); + let ip = acvm.instruction_pointer(); + let opcodes = acvm.opcodes(); + if ip >= opcodes.len() { + println!("Finished execution"); + } else { + println!("Stopped at opcode {}: {}", ip, opcodes[ip]); + Self::show_source_code_location(&OpcodeLocation::Acir(ip), &self.debug_artifact); + } } fn show_source_code_location(location: &OpcodeLocation, debug_artifact: &DebugArtifact) { @@ -119,6 +125,10 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { } Ok(SolveResult::Done) } + + fn finalize(&mut self) -> WitnessMap { + self.acvm.take().unwrap().finalize() + } } impl From for DebuggingError { @@ -156,12 +166,12 @@ pub fn debug_circuit( let ref_step = &context; let ref_cont = &context; - let solved = RefCell::new(false); + let solved = Cell::new(false); context.borrow().show_current_vm_status(); let handle_result = |result| { - solved.replace(match result { + solved.set(match result { SolveResult::Done => true, _ => false, }); @@ -196,9 +206,8 @@ pub fn debug_circuit( repl.run().expect("Debugger error"); - let acvm = context.borrow_mut().acvm.take().unwrap(); - if *solved.borrow() { - let solved_witness = acvm.finalize(); + if solved.get() { + let solved_witness = context.borrow_mut().finalize(); Ok(solved_witness) } else { Err(NargoError::ExecutionError(ExecutionError::Halted)) From 258d00974a4eb1b0dbc57b6767741973071dd5ac Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Wed, 11 Oct 2023 12:22:26 +0200 Subject: [PATCH 12/19] Update tooling/nargo_cli/src/cli/debug_cmd.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- tooling/nargo_cli/src/cli/debug_cmd.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 5f457d9fe2d..12d87366172 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -107,15 +107,11 @@ pub(crate) fn debug_program( file_map: compiled_program.file_map.clone(), }; - let solved_witness_err = noir_debugger::debug_circuit( + noir_debugger::debug_circuit( &blackbox_solver, compiled_program.circuit.clone(), debug_artifact, initial_witness, true, - ); - match solved_witness_err { - Ok(solved_witness) => Ok(solved_witness), - Err(err) => Err(crate::errors::CliError::NargoError(err)), - } + ).map_err(CliError::from) } From 449d16eb20f231c12b59eb07848aea6555d99edf Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 12 Oct 2023 12:34:46 +0200 Subject: [PATCH 13/19] Debugger: explicitly restrict to binary packages --- tooling/nargo_cli/src/cli/debug_cmd.rs | 63 +++++++++++++++----------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 12d87366172..6d141309a30 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -28,10 +28,6 @@ pub(crate) struct DebugCommand { #[clap(long, short, default_value = PROVER_INPUT_FILE)] prover_name: String, - /// Detail all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, - /// The name of the package to execute #[clap(long)] package: Option, @@ -49,30 +45,42 @@ pub(crate) fn run( let selection = args.package.map_or(PackageSelection::DefaultOrAll, PackageSelection::Selected); let workspace = resolve_workspace_from_toml(&toml_path, selection)?; let target_dir = &workspace.target_directory_path(); - let (np_language, opcode_support) = backend.get_backend_info()?; - for package in &workspace { - let compiled_program = compile_bin_package( - &workspace, - package, - &args.compile_options, - true, - np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), - )?; - - println!("[{}] Starting debugger", package.name); - let (return_value, solved_witness) = - debug_program_and_decode(compiled_program, package, &args.prover_name)?; - - println!("[{}] Circuit witness successfully solved", package.name); - if let Some(return_value) = return_value { - println!("[{}] Circuit output: {return_value:?}", package.name); - } - if let Some(witness_name) = &args.witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; - println!("[{}] Witness saved to {}", package.name, witness_path.display()); + if workspace.into_iter().filter(|p| p.is_binary()).count() == 0 { + println!( + "No matching binary packages found in workspace. Only binary packages can be debugged." + ); + return Ok(()); + } + + for package in &workspace { + if package.is_binary() { + let compiled_program = compile_bin_package( + &workspace, + package, + &args.compile_options, + true, + np_language, + &|opcode| opcode_support.is_opcode_supported(opcode), + )?; + + println!("[{}] Starting debugger", package.name); + let (return_value, solved_witness) = + debug_program_and_decode(compiled_program, package, &args.prover_name)?; + + println!("[{}] Circuit witness successfully solved", package.name); + if let Some(return_value) = return_value { + println!("[{}] Circuit output: {return_value:?}", package.name); + } + if let Some(witness_name) = &args.witness_name { + let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + } + + // Only debug the first binary package that matches the selection criteria + break; } } Ok(()) @@ -113,5 +121,6 @@ pub(crate) fn debug_program( debug_artifact, initial_witness, true, - ).map_err(CliError::from) + ) + .map_err(CliError::from) } From c3a3138ab8afb1b84cb7d4abcf3d782d332031c0 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 12 Oct 2023 13:55:32 +0200 Subject: [PATCH 14/19] Handle debug halt as expected result --- tooling/debugger/src/lib.rs | 34 +++++--------------------- tooling/nargo/src/errors.rs | 4 --- tooling/nargo_cli/src/cli/debug_cmd.rs | 34 +++++++++++++++++--------- 3 files changed, 29 insertions(+), 43 deletions(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 306b8c7f301..9843e628988 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -9,8 +9,6 @@ use nargo::NargoError; use nargo::ops::ForeignCallExecutor; -use thiserror::Error; - use easy_repl::{command, CommandStatus, Critical, Repl}; use std::cell::{Cell, RefCell}; @@ -19,17 +17,6 @@ enum SolveResult { Ok, } -#[derive(Debug, Error)] -enum DebuggingError { - /// ACIR circuit execution error - #[error(transparent)] - ExecutionError(#[from] nargo::errors::ExecutionError), - - /// Oracle handling error - #[error(transparent)] - ForeignCallError(#[from] noirc_printable_type::ForeignCallError), -} - struct DebugContext<'backend, B: BlackBoxFunctionSolver> { acvm: Option>, debug_artifact: DebugArtifact, @@ -39,7 +26,7 @@ struct DebugContext<'backend, B: BlackBoxFunctionSolver> { } impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { - fn step_opcode(&mut self) -> Result { + fn step_opcode(&mut self) -> Result { // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 let assert_messages = &self.circuit.assert_messages; let get_assert_message = |opcode_location| { @@ -65,7 +52,7 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { _ => None, }; - Err(DebuggingError::ExecutionError(match call_stack { + Err(NargoError::ExecutionError(match call_stack { Some(call_stack) => { if let Some(assert_message) = get_assert_message( call_stack.last().expect("Call stacks should not be empty"), @@ -116,7 +103,7 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { } } - fn cont(&mut self) -> Result { + fn cont(&mut self) -> Result { loop { match self.step_opcode()? { SolveResult::Done => break, @@ -131,15 +118,6 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { } } -impl From for DebuggingError { - fn from(e: nargo::errors::NargoError) -> Self { - match e { - NargoError::ForeignCallError(e1) => DebuggingError::ForeignCallError(e1), - _ => DebuggingError::ExecutionError(ExecutionError::Halted), - } - } -} - fn map_command_status(result: SolveResult) -> CommandStatus { match result { SolveResult::Ok => CommandStatus::Done, @@ -153,7 +131,7 @@ pub fn debug_circuit( debug_artifact: DebugArtifact, initial_witness: WitnessMap, show_output: bool, -) -> Result { +) -> Result, NargoError> { let opcodes = circuit.opcodes.clone(); let context = RefCell::new(DebugContext { @@ -208,8 +186,8 @@ pub fn debug_circuit( if solved.get() { let solved_witness = context.borrow_mut().finalize(); - Ok(solved_witness) + Ok(Some(solved_witness)) } else { - Err(NargoError::ExecutionError(ExecutionError::Halted)) + Ok(None) } } diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index dd68bfbc037..ea6e7fa8108 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -49,7 +49,6 @@ impl NargoError { OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message), OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => Some(reason), }, - ExecutionError::Halted => None, } } } @@ -61,9 +60,6 @@ pub enum ExecutionError { #[error(transparent)] SolvingError(#[from] OpcodeResolutionError), - - #[error("Execution halted")] - Halted, } /// Extracts the opcode locations from a nargo error. diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 6d141309a30..81b0cf566b1 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -69,14 +69,21 @@ pub(crate) fn run( let (return_value, solved_witness) = debug_program_and_decode(compiled_program, package, &args.prover_name)?; - println!("[{}] Circuit witness successfully solved", package.name); - if let Some(return_value) = return_value { - println!("[{}] Circuit output: {return_value:?}", package.name); - } - if let Some(witness_name) = &args.witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + if let Some(solved_witness) = solved_witness { + println!("[{}] Circuit witness successfully solved", package.name); + + if let Some(return_value) = return_value { + println!("[{}] Circuit output: {return_value:?}", package.name); + } + + if let Some(witness_name) = &args.witness_name { + let witness_path = + save_witness_to_dir(solved_witness, witness_name, target_dir)?; - println!("[{}] Witness saved to {}", package.name, witness_path.display()); + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + } + } else { + println!("Debugger execution halted."); } // Only debug the first binary package that matches the selection criteria @@ -90,21 +97,26 @@ fn debug_program_and_decode( program: CompiledProgram, package: &Package, prover_name: &str, -) -> Result<(Option, WitnessMap), CliError> { +) -> Result<(Option, Option), CliError> { // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; let solved_witness = debug_program(&program, &inputs_map)?; let public_abi = program.abi.public_abi(); - let (_, return_value) = public_abi.decode(&solved_witness)?; - Ok((return_value, solved_witness)) + match solved_witness { + Some(witness) => { + let (_, return_value) = public_abi.decode(&witness)?; + Ok((return_value, Some(witness))) + } + None => Ok((None, None)), + } } pub(crate) fn debug_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, -) -> Result { +) -> Result, CliError> { #[allow(deprecated)] let blackbox_solver = barretenberg_blackbox_solver::BarretenbergSolver::new(); From e4586b0e7ad8301b9df633a1fe9af345c8d6b858 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 12 Oct 2023 16:20:17 +0200 Subject: [PATCH 15/19] Update tooling/debugger/src/lib.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- tooling/debugger/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 9843e628988..ff318cd9ca5 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -54,10 +54,10 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { Err(NargoError::ExecutionError(match call_stack { Some(call_stack) => { - if let Some(assert_message) = get_assert_message( - call_stack.last().expect("Call stacks should not be empty"), + if let Some(assert_message) = circuit.get_assert_message( + *call_stack.last().expect("Call stacks should not be empty"), ) { - ExecutionError::AssertionFailed(assert_message, call_stack) + ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) } else { ExecutionError::SolvingError(error) } From dd30bcaeb588acf53a2a469dcf882fa0fe9e34ce Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 12 Oct 2023 16:27:06 +0200 Subject: [PATCH 16/19] Bring up to date to latest ACVM/Brillig refactors --- tooling/debugger/src/lib.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index ff318cd9ca5..ed9b89cbee8 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -27,15 +27,6 @@ struct DebugContext<'backend, B: BlackBoxFunctionSolver> { impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { fn step_opcode(&mut self) -> Result { - // Assert messages are not a map due to https://github.com/noir-lang/acvm/issues/522 - let assert_messages = &self.circuit.assert_messages; - let get_assert_message = |opcode_location| { - assert_messages - .iter() - .find(|(loc, _)| loc == opcode_location) - .map(|(_, message)| message.clone()) - }; - let solver_status = self.acvm.as_mut().unwrap().solve_opcode(); match solver_status { @@ -54,7 +45,7 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { Err(NargoError::ExecutionError(match call_stack { Some(call_stack) => { - if let Some(assert_message) = circuit.get_assert_message( + if let Some(assert_message) = self.circuit.get_assert_message( *call_stack.last().expect("Call stacks should not be empty"), ) { ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) @@ -135,7 +126,7 @@ pub fn debug_circuit( let opcodes = circuit.opcodes.clone(); let context = RefCell::new(DebugContext { - acvm: Some(ACVM::new(blackbox_solver, opcodes, initial_witness)), + acvm: Some(ACVM::new(blackbox_solver, &opcodes, initial_witness)), foreign_call_executor: ForeignCallExecutor::default(), circuit, debug_artifact, From f20d0e1a520128ec1889305d8615f33aa21c2637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 12 Oct 2023 18:57:48 -0400 Subject: [PATCH 17/19] chore: Simplify selection/validation of package for debugging --- tooling/nargo_cli/src/cli/debug_cmd.rs | 65 ++++++++++++-------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 81b0cf566b1..9a1115ae7be 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -47,49 +47,42 @@ pub(crate) fn run( let target_dir = &workspace.target_directory_path(); let (np_language, opcode_support) = backend.get_backend_info()?; - if workspace.into_iter().filter(|p| p.is_binary()).count() == 0 { + let Some(package) = workspace.into_iter().find(|p| p.is_binary()) else { println!( "No matching binary packages found in workspace. Only binary packages can be debugged." ); return Ok(()); - } + }; + + let compiled_program = compile_bin_package( + &workspace, + package, + &args.compile_options, + true, + np_language, + &|opcode| opcode_support.is_opcode_supported(opcode), + )?; + + println!("[{}] Starting debugger", package.name); + let (return_value, solved_witness) = + debug_program_and_decode(compiled_program, package, &args.prover_name)?; - for package in &workspace { - if package.is_binary() { - let compiled_program = compile_bin_package( - &workspace, - package, - &args.compile_options, - true, - np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), - )?; - - println!("[{}] Starting debugger", package.name); - let (return_value, solved_witness) = - debug_program_and_decode(compiled_program, package, &args.prover_name)?; - - if let Some(solved_witness) = solved_witness { - println!("[{}] Circuit witness successfully solved", package.name); - - if let Some(return_value) = return_value { - println!("[{}] Circuit output: {return_value:?}", package.name); - } - - if let Some(witness_name) = &args.witness_name { - let witness_path = - save_witness_to_dir(solved_witness, witness_name, target_dir)?; - - println!("[{}] Witness saved to {}", package.name, witness_path.display()); - } - } else { - println!("Debugger execution halted."); - } - - // Only debug the first binary package that matches the selection criteria - break; + if let Some(solved_witness) = solved_witness { + println!("[{}] Circuit witness successfully solved", package.name); + + if let Some(return_value) = return_value { + println!("[{}] Circuit output: {return_value:?}", package.name); } + + if let Some(witness_name) = &args.witness_name { + let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + } + } else { + println!("Debugger execution halted."); } + Ok(()) } From 8622d7021a59a09cd1bf8ca4061739e84895e3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 12 Oct 2023 22:59:05 -0400 Subject: [PATCH 18/19] chore: apply clippy suggestions --- tooling/debugger/src/lib.rs | 26 ++++++++++---------------- tooling/nargo_cli/src/cli/debug_cmd.rs | 2 -- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index ed9b89cbee8..d7690411965 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -78,19 +78,16 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { } fn show_source_code_location(location: &OpcodeLocation, debug_artifact: &DebugArtifact) { - let locations = debug_artifact.debug_symbols[0].opcode_location(&location); - match locations { - Some(locations) => { - for loc in locations { - let file = &debug_artifact.file_map[&loc.file]; - let source = &file.source.as_str(); - let start = loc.span.start() as usize; - let end = loc.span.end() as usize; - println!("At {}:{start}-{end}", file.path.as_path().display()); - println!("\n{}\n", &source[start..end]); - } + let locations = debug_artifact.debug_symbols[0].opcode_location(location); + if let Some(locations) = locations { + for loc in locations { + let file = &debug_artifact.file_map[&loc.file]; + let source = &file.source.as_str(); + let start = loc.span.start() as usize; + let end = loc.span.end() as usize; + println!("At {}:{start}-{end}", file.path.as_path().display()); + println!("\n{}\n", &source[start..end]); } - None => {} } } @@ -140,10 +137,7 @@ pub fn debug_circuit( context.borrow().show_current_vm_status(); let handle_result = |result| { - solved.set(match result { - SolveResult::Done => true, - _ => false, - }); + solved.set(matches!(result, SolveResult::Done)); Ok(map_command_status(result)) }; diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 9a1115ae7be..5dcb2c7bdec 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -10,8 +10,6 @@ use noirc_abi::InputMap; use noirc_driver::{CompileOptions, CompiledProgram}; use noirc_frontend::graph::CrateName; -use noir_debugger; - use super::compile_cmd::compile_bin_package; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; use super::NargoConfig; From f0b3ecff9eb9be24419cb7d4c1395c80b268a384 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Fri, 13 Oct 2023 15:11:25 +0200 Subject: [PATCH 19/19] Update tooling/debugger/src/lib.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- tooling/debugger/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index d7690411965..ed9fe08ca97 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -85,7 +85,7 @@ impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { let source = &file.source.as_str(); let start = loc.span.start() as usize; let end = loc.span.end() as usize; - println!("At {}:{start}-{end}", file.path.as_path().display()); + println!("At {}.nr:{start}-{end}", file.path.as_path().display()); println!("\n{}\n", &source[start..end]); } }