From c47e701cb3191b72ddbd0693b2ad58343da03ebb Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 11:29:02 -0300 Subject: [PATCH 01/52] Start get_traceback_entries + add convenience methos --- src/vm/vm_core.rs | 28 ++++++++++++++++++++++++++++ src/vm/vm_memory/memory.rs | 13 +++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 0a13450fc6..392b7d0822 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -26,6 +26,8 @@ use num_integer::Integer; use num_traits::{ToPrimitive, Zero}; use std::{any::Any, borrow::Cow, collections::HashMap}; +const MAX_TRACEBACK_ENTRIES: u32 = 20; + #[derive(PartialEq, Debug)] pub struct Operands { dst: MaybeRelocatable, @@ -727,6 +729,32 @@ impl VirtualMachine { } } + // Returns the values (fp, pc) corresponding to each call instruction in the traceback. + // Returns the most recent call last. + // The returned values consist of the offsets, not the full addresses as the index is constant + pub(crate) fn get_traceback_entries(&self) -> Vec<(usize, usize)> { + let entries = Vec::<(usize, usize)>::new(); + let fp = Relocatable::from((1, self.run_context.fp)); + for _ in 0..MAX_TRACEBACK_ENTRIES { + if let (Some(Ok(opt_fp)), Some(Ok(opt_ret_pc))) = ( + fp.sub(2) + .ok() + .map(|ref r| self.memory.get_owned_relocatable(r)), + fp.sub(1) + .ok() + .map(|ref r| self.memory.get_owned_relocatable(r)), + ) { + // Check that memory.get(fp -2) != fp + if opt_fp == fp { + break; + }; + } else { + break; + } + } + entries + } + ///Adds a new segment and to the VirtualMachine.memory returns its starting location as a RelocatableValue. pub fn add_memory_segment(&mut self) -> Relocatable { self.segments.add(&mut self.memory) diff --git a/src/vm/vm_memory/memory.rs b/src/vm/vm_memory/memory.rs index 60cae3a6b4..b0a716f921 100644 --- a/src/vm/vm_memory/memory.rs +++ b/src/vm/vm_memory/memory.rs @@ -263,6 +263,19 @@ impl Memory { } } + pub fn get_owned_relocatable( + &self, + key: &Relocatable, + ) -> Result { + match self.get(key).map_err(VirtualMachineError::MemoryError)? { + Some(Cow::Borrowed(MaybeRelocatable::RelocatableValue(rel))) => Ok(rel.clone()), + Some(Cow::Owned(MaybeRelocatable::RelocatableValue(rel))) => Ok(rel), + _ => Err(VirtualMachineError::ExpectedRelocatable( + MaybeRelocatable::from(key), + )), + } + } + pub fn insert_value>( &mut self, key: &Relocatable, From 51219ca4f2b877f22abd1ed9900bf91bc23104ae Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 13:00:55 -0300 Subject: [PATCH 02/52] Add fn is_call_instruction --- src/types/instruction.rs | 20 ++++++++++++++++++++ src/vm/decoding/decoder.rs | 3 +-- src/vm/vm_core.rs | 11 ++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index 7140c6ef0f..7372119f21 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -1,6 +1,9 @@ use num_bigint::BigInt; +use num_traits::ToPrimitive; use serde::Deserialize; +use crate::vm::decoding::decoder::decode_instruction; + #[derive(Deserialize, Debug, PartialEq, Eq, Clone)] pub enum Register { AP, @@ -78,3 +81,20 @@ impl Instruction { } } } + +// Returns True if the given instruction looks like a call instruction. +pub(crate) fn is_call_instruction(encoded_instruction: BigInt, imm: Option) -> bool { + let encoded_i64_instruction = match encoded_instruction.to_i64() { + Some(num) => num, + None => return false, + }; + let instruction = match decode_instruction(encoded_i64_instruction, imm) { + Ok(inst) => inst, + Err(_) => return false, + }; + return instruction.res == Res::Op1 + && (instruction.pc_update == PcUpdate::Jump || instruction.pc_update == PcUpdate::JumpRel) + && instruction.ap_update == ApUpdate::Add2 + && instruction.fp_update == FpUpdate::APPlus2 + && instruction.opcode == Opcode::Call; +} diff --git a/src/vm/decoding/decoder.rs b/src/vm/decoding/decoder.rs index d408fc6a49..432aeda40e 100644 --- a/src/vm/decoding/decoder.rs +++ b/src/vm/decoding/decoder.rs @@ -1,5 +1,4 @@ -use crate::types::instruction; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::{types::instruction, vm::errors::vm_errors::VirtualMachineError}; use num_bigint::BigInt; // 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 392b7d0822..15fabc97c5 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -734,7 +734,7 @@ impl VirtualMachine { // The returned values consist of the offsets, not the full addresses as the index is constant pub(crate) fn get_traceback_entries(&self) -> Vec<(usize, usize)> { let entries = Vec::<(usize, usize)>::new(); - let fp = Relocatable::from((1, self.run_context.fp)); + let mut fp = Relocatable::from((1, self.run_context.fp)); for _ in 0..MAX_TRACEBACK_ENTRIES { if let (Some(Ok(opt_fp)), Some(Ok(opt_ret_pc))) = ( fp.sub(2) @@ -748,6 +748,15 @@ impl VirtualMachine { if opt_fp == fp { break; }; + fp = opt_fp; + let ret_pc = opt_ret_pc; + if let (Some(Ok(instruction0)), Some(Ok(instruction1))) = ( + ret_pc.sub(2).ok().map(|ref r| self.memory.get_integer(r)), + ret_pc.sub(1).ok().map(|ref r| self.memory.get_integer(r)), + ) { + } else { + break; + } } else { break; } From 3b276dbdfb224f713b44584e8810ad4ecc24654f Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 14:38:45 -0300 Subject: [PATCH 03/52] add code --- src/types/instruction.rs | 6 ++++-- src/vm/vm_core.rs | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index 7372119f21..cd4664bd5e 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use num_bigint::BigInt; use num_traits::ToPrimitive; use serde::Deserialize; @@ -83,8 +85,8 @@ impl Instruction { } // Returns True if the given instruction looks like a call instruction. -pub(crate) fn is_call_instruction(encoded_instruction: BigInt, imm: Option) -> bool { - let encoded_i64_instruction = match encoded_instruction.to_i64() { +pub(crate) fn is_call_instruction(encoded_instruction: &Cow, imm: Option) -> bool { + let encoded_i64_instruction: i64 = match encoded_instruction.to_i64() { Some(num) => num, None => return false, }; diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 15fabc97c5..ba734e8a56 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -9,7 +9,9 @@ use crate::{ serde::deserialize_program::{ApTracking, Attribute}, types::{ exec_scope::ExecutionScopes, - instruction::{ApUpdate, FpUpdate, Instruction, Opcode, PcUpdate, Res}, + instruction::{ + is_call_instruction, ApUpdate, FpUpdate, Instruction, Opcode, PcUpdate, Res, + }, relocatable::{MaybeRelocatable, Relocatable}, }, vm::{ @@ -731,13 +733,12 @@ impl VirtualMachine { // Returns the values (fp, pc) corresponding to each call instruction in the traceback. // Returns the most recent call last. - // The returned values consist of the offsets, not the full addresses as the index is constant - pub(crate) fn get_traceback_entries(&self) -> Vec<(usize, usize)> { - let entries = Vec::<(usize, usize)>::new(); + pub(crate) fn get_traceback_entries(&self) -> Vec<(Relocatable, Relocatable)> { + let mut entries = Vec::<(Relocatable, Relocatable)>::new(); let mut fp = Relocatable::from((1, self.run_context.fp)); for _ in 0..MAX_TRACEBACK_ENTRIES { if let (Some(Ok(opt_fp)), Some(Ok(opt_ret_pc))) = ( - fp.sub(2) + &fp.sub(2) .ok() .map(|ref r| self.memory.get_owned_relocatable(r)), fp.sub(1) @@ -750,10 +751,27 @@ impl VirtualMachine { }; fp = opt_fp; let ret_pc = opt_ret_pc; - if let (Some(Ok(instruction0)), Some(Ok(instruction1))) = ( - ret_pc.sub(2).ok().map(|ref r| self.memory.get_integer(r)), - ret_pc.sub(1).ok().map(|ref r| self.memory.get_integer(r)), - ) { + // Get the two memory cells before ret_pc. + if let Some(Ok(instruction1)) = + ret_pc.sub(1).ok().map(|ref r| self.memory.get_integer(r)) + { + // Try to check if the call instruction is (instruction0, instruction1) or just + // instruction1 (with no immediate). + let mut call_pc = Relocatable::from((9, 9)); // initial val + if is_call_instruction(&instruction1, None) { + call_pc = ret_pc.sub(1).unwrap(); // This unwrap wont fail as we checked it before + } else { + if let Some(Ok(instruction0)) = + ret_pc.sub(2).ok().map(|ref r| self.memory.get_integer(r)) + { + if is_call_instruction(&instruction0, Some(instruction1.into_owned())) { + call_pc = ret_pc.sub(2).unwrap(); // This unwrap wont fail as we checked it before + } else { + break; + } + } + } + entries.push((fp, call_pc)) } else { break; } @@ -761,6 +779,7 @@ impl VirtualMachine { break; } } + entries.reverse(); entries } From c89eb3f20837f94a8ce9a5ec73b65c54c3f66dab Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 15:04:58 -0300 Subject: [PATCH 04/52] Refactor code --- src/vm/vm_core.rs | 78 +++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 8035bc1cfb..c09bfd544f 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -740,48 +740,52 @@ impl VirtualMachine { pub(crate) fn get_traceback_entries(&self) -> Vec<(Relocatable, Relocatable)> { let mut entries = Vec::<(Relocatable, Relocatable)>::new(); let mut fp = Relocatable::from((1, self.run_context.fp)); + // Fetch the fp and pc traceback entries for _ in 0..MAX_TRACEBACK_ENTRIES { - if let (Some(Ok(opt_fp)), Some(Ok(opt_ret_pc))) = ( - &fp.sub(2) - .ok() - .map(|ref r| self.memory.get_owned_relocatable(r)), - fp.sub(1) - .ok() - .map(|ref r| self.memory.get_owned_relocatable(r)), - ) { - // Check that memory.get(fp -2) != fp - if opt_fp == fp { - break; - }; - fp = opt_fp; - let ret_pc = opt_ret_pc; - // Get the two memory cells before ret_pc. - if let Some(Ok(instruction1)) = - ret_pc.sub(1).ok().map(|ref r| self.memory.get_integer(r)) - { - // Try to check if the call instruction is (instruction0, instruction1) or just - // instruction1 (with no immediate). - let mut call_pc = Relocatable::from((9, 9)); // initial val - if is_call_instruction(&instruction1, None) { - call_pc = ret_pc.sub(1).unwrap(); // This unwrap wont fail as we checked it before - } else { - if let Some(Ok(instruction0)) = - ret_pc.sub(2).ok().map(|ref r| self.memory.get_integer(r)) - { - if is_call_instruction(&instruction0, Some(instruction1.into_owned())) { - call_pc = ret_pc.sub(2).unwrap(); // This unwrap wont fail as we checked it before - } else { - break; + // First we get the fp traceback + match fp + .sub(2) + .ok() + .map(|ref r| self.memory.get_owned_relocatable(r)) + { + Some(Ok(opt_fp)) if opt_fp != fp => fp = opt_fp, + _ => break, + } + // Then we get the pc traceback + let ret_pc = match fp + .sub(1) + .ok() + .map(|ref r| self.memory.get_owned_relocatable(r)) + { + Some(Ok(opt_pc)) => opt_pc, + _ => break, + }; + // Try to check if the call instruction is (instruction0, instruction1) or just + // instruction1 (with no immediate). + let call_pc = match ret_pc.sub(1).ok().map(|ref r| self.memory.get_integer(r)) { + Some(Ok(instruction1)) => { + match is_call_instruction(&instruction1, None) { + true => ret_pc.sub(1).unwrap(), // This unwrap wont fail as it is checked before + false => { + match ret_pc.sub(2).ok().map(|ref r| self.memory.get_integer(r)) { + Some(Ok(instruction0)) => { + match is_call_instruction( + &instruction0, + Some(instruction1.into_owned()), + ) { + true => ret_pc.sub(1).unwrap(), // This unwrap wont fail as it is checked before + false => break, + } + } + _ => break, } } } - entries.push((fp, call_pc)) - } else { - break; } - } else { - break; - } + _ => break, + }; + // Append traceback entries + entries.push((fp, call_pc)) } entries.reverse(); entries From f02db3ebe47e3bf253324b3f6f0b251bd76dbcee Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 15:08:00 -0300 Subject: [PATCH 05/52] Clippy --- src/types/instruction.rs | 6 +++--- src/vm/vm_core.rs | 12 ++---------- src/vm/vm_memory/memory.rs | 13 ------------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index cd4664bd5e..4387f15943 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -85,7 +85,7 @@ impl Instruction { } // Returns True if the given instruction looks like a call instruction. -pub(crate) fn is_call_instruction(encoded_instruction: &Cow, imm: Option) -> bool { +pub(crate) fn is_call_instruction(encoded_instruction: &BigInt, imm: Option) -> bool { let encoded_i64_instruction: i64 = match encoded_instruction.to_i64() { Some(num) => num, None => return false, @@ -94,9 +94,9 @@ pub(crate) fn is_call_instruction(encoded_instruction: &Cow, imm: Option Ok(inst) => inst, Err(_) => return false, }; - return instruction.res == Res::Op1 + instruction.res == Res::Op1 && (instruction.pc_update == PcUpdate::Jump || instruction.pc_update == PcUpdate::JumpRel) && instruction.ap_update == ApUpdate::Add2 && instruction.fp_update == FpUpdate::APPlus2 - && instruction.opcode == Opcode::Call; + && instruction.opcode == Opcode::Call } diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index c09bfd544f..d9b075fb9f 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -743,20 +743,12 @@ impl VirtualMachine { // Fetch the fp and pc traceback entries for _ in 0..MAX_TRACEBACK_ENTRIES { // First we get the fp traceback - match fp - .sub(2) - .ok() - .map(|ref r| self.memory.get_owned_relocatable(r)) - { + match fp.sub(2).ok().map(|ref r| self.memory.get_relocatable(r)) { Some(Ok(opt_fp)) if opt_fp != fp => fp = opt_fp, _ => break, } // Then we get the pc traceback - let ret_pc = match fp - .sub(1) - .ok() - .map(|ref r| self.memory.get_owned_relocatable(r)) - { + let ret_pc = match fp.sub(1).ok().map(|ref r| self.memory.get_relocatable(r)) { Some(Ok(opt_pc)) => opt_pc, _ => break, }; diff --git a/src/vm/vm_memory/memory.rs b/src/vm/vm_memory/memory.rs index d3b720a251..d91b01cdba 100644 --- a/src/vm/vm_memory/memory.rs +++ b/src/vm/vm_memory/memory.rs @@ -260,19 +260,6 @@ impl Memory { } } - pub fn get_owned_relocatable( - &self, - key: &Relocatable, - ) -> Result { - match self.get(key).map_err(VirtualMachineError::MemoryError)? { - Some(Cow::Borrowed(MaybeRelocatable::RelocatableValue(rel))) => Ok(rel.clone()), - Some(Cow::Owned(MaybeRelocatable::RelocatableValue(rel))) => Ok(rel), - _ => Err(VirtualMachineError::ExpectedRelocatable( - MaybeRelocatable::from(key), - )), - } - } - pub fn insert_value>( &mut self, key: &Relocatable, From 05813bd60da7009e81d9269e5257ff84535ab88f Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 16:33:31 -0300 Subject: [PATCH 06/52] Add get_traceback method --- src/vm/errors/vm_exception.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 2ed601bebb..c30e1b8cf4 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -2,7 +2,10 @@ use std::fmt::{self, Display}; use thiserror::Error; -use crate::{serde::deserialize_program::Location, vm::runners::cairo_runner::CairoRunner}; +use crate::{ + serde::deserialize_program::Location, + vm::{runners::cairo_runner::CairoRunner, vm_core::VirtualMachine}, +}; use super::vm_errors::VirtualMachineError; #[derive(Debug, PartialEq, Error)] @@ -25,6 +28,7 @@ impl VmException { } } +//MISSING LOGIC HERE -> fp param pub fn get_error_attr_value(pc: usize, runner: &CairoRunner) -> Option { for attribute in &runner.program.error_message_attributes { if attribute.start_pc <= pc && attribute.end_pc > pc { @@ -43,6 +47,30 @@ pub fn get_location(pc: &usize, runner: &CairoRunner) -> Option { .cloned() } +// Returns the traceback at the current pc. +pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option { + let mut traceback = String::new(); + for (_fp, traceback_pc) in vm.get_traceback_entries() { + if let Some(ref attr) = get_error_attr_value(traceback_pc.offset, runner) { + traceback.push_str(attr) + } + match get_location(&traceback_pc.offset, runner) { + Some(location) => { + traceback.push_str(&location.to_string(&format!("(pc={})\n", traceback_pc.offset))) + } + None => traceback.push_str(&format!("Unknown location (pc={})\n", traceback_pc.offset)), + } + } + if traceback.is_empty() { + None + } else { + Some(format!( + "Cairo traceback (most recent call last):\n{}", + traceback + )) + } +} + impl Display for VmException { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Build initial message From 58992c31b11826991d35e6c4b6fafca64271025c Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 16:43:41 -0300 Subject: [PATCH 07/52] Fix get_error_attr_value --- src/types/instruction.rs | 2 -- src/vm/errors/vm_exception.rs | 16 +++++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index 4387f15943..5c98e94f3c 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use num_bigint::BigInt; use num_traits::ToPrimitive; use serde::Deserialize; diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index c30e1b8cf4..495bf0d9f6 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -28,14 +28,14 @@ impl VmException { } } -//MISSING LOGIC HERE -> fp param pub fn get_error_attr_value(pc: usize, runner: &CairoRunner) -> Option { + let mut errors = String::new(); for attribute in &runner.program.error_message_attributes { if attribute.start_pc <= pc && attribute.end_pc > pc { - return Some(format!("Error message: {}\n", attribute.value)); + errors.push_str(&format!("Error message: {}\n", attribute.value)); } } - None + (!errors.is_empty()).then(|| errors) } pub fn get_location(pc: &usize, runner: &CairoRunner) -> Option { @@ -61,14 +61,8 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option traceback.push_str(&format!("Unknown location (pc={})\n", traceback_pc.offset)), } } - if traceback.is_empty() { - None - } else { - Some(format!( - "Cairo traceback (most recent call last):\n{}", - traceback - )) - } + (!traceback.is_empty()) + .then(|| format!("Cairo traceback (most recent call last):\n{}", traceback)) } impl Display for VmException { From b3816246f9c316194f097e105ef4885c19bea399 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 17:02:17 -0300 Subject: [PATCH 08/52] Add traceback to VmException --- src/cairo_run.rs | 2 +- src/vm/errors/vm_exception.rs | 38 ++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/cairo_run.rs b/src/cairo_run.rs index 3c478f97d7..c99436b30b 100644 --- a/src/cairo_run.rs +++ b/src/cairo_run.rs @@ -34,7 +34,7 @@ pub fn cairo_run( cairo_runner .run_until_pc(end, &mut vm, hint_executor) - .map_err(|err| VmException::from_vm_error(&cairo_runner, err, vm.run_context.pc.offset))?; + .map_err(|err| VmException::from_vm_error(&cairo_runner, &vm, err))?; cairo_runner.end_run(false, false, &mut vm, hint_executor)?; vm.verify_auto_deductions()?; diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 495bf0d9f6..0f09378fa0 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -14,16 +14,23 @@ pub struct VmException { inst_location: Option, inner_exc: VirtualMachineError, error_attr_value: Option, + traceback: Option, } impl VmException { - pub fn from_vm_error(runner: &CairoRunner, error: VirtualMachineError, pc: usize) -> Self { - let error_attr_value = get_error_attr_value(pc, runner); + pub fn from_vm_error( + runner: &CairoRunner, + vm: &VirtualMachine, + error: VirtualMachineError, + with_traceback: bool, + ) -> Self { + let error_attr_value = get_error_attr_value(vm.run_context.pc.offset, runner); VmException { - pc, - inst_location: get_location(&pc, runner), + pc: vm.run_context.pc.offset, + inst_location: get_location(vm.run_context.pc.offset, runner), inner_exc: error, error_attr_value, + traceback: with_traceback.then(|| get_traceback(vm, runner)).flatten(), } } } @@ -38,12 +45,12 @@ pub fn get_error_attr_value(pc: usize, runner: &CairoRunner) -> Option { (!errors.is_empty()).then(|| errors) } -pub fn get_location(pc: &usize, runner: &CairoRunner) -> Option { +pub fn get_location(pc: usize, runner: &CairoRunner) -> Option { runner .program .instruction_locations .as_ref()? - .get(pc) + .get(&pc) .cloned() } @@ -54,7 +61,7 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option { traceback.push_str(&location.to_string(&format!("(pc={})\n", traceback_pc.offset))) } @@ -108,6 +115,7 @@ impl Location { } #[cfg(test)] mod test { + use num_bigint::{BigInt, Sign}; use std::collections::HashMap; use crate::serde::deserialize_program::{Attribute, InputFile}; @@ -137,9 +145,15 @@ mod test { inst_location: Some(location), inner_exc: VirtualMachineError::CouldntPopPositions, error_attr_value: None, + traceback: None, }; assert_eq!( - VmException::from_vm_error(&runner, VirtualMachineError::CouldntPopPositions, pc), + VmException::from_vm_error( + &runner, + &vm!(), + VirtualMachineError::CouldntPopPositions, + false + ), vm_excep ) } @@ -192,6 +206,7 @@ mod test { Relocatable::from((0, 4)), ), error_attr_value: None, + traceback: None, }; assert_eq!( vm_excep.to_string(), @@ -215,6 +230,7 @@ mod test { Relocatable::from((0, 4)), ), error_attr_value: Some(String::from("Error message: Block may fail\n")), + traceback: None, }; assert_eq!( vm_excep.to_string(), @@ -248,6 +264,7 @@ mod test { Relocatable::from((0, 4)), ), error_attr_value: None, + traceback: None, }; assert_eq!( vm_excep.to_string(), @@ -293,6 +310,7 @@ mod test { Relocatable::from((0, 4)), ), error_attr_value: None, + traceback: None, }; assert_eq!( vm_excep.to_string(), @@ -347,7 +365,7 @@ mod test { let program = program!(instruction_locations = Some(HashMap::from([(2, location.clone())])),); let runner = cairo_runner!(program); - assert_eq!(get_location(&2, &runner), Some(location)); + assert_eq!(get_location(2, &runner), Some(location)); } #[test] @@ -364,6 +382,6 @@ mod test { }; let program = program!(instruction_locations = Some(HashMap::from([(2, location)])),); let runner = cairo_runner!(program); - assert_eq!(get_location(&3, &runner), None); + assert_eq!(get_location(3, &runner), None); } } From 936eadce60a70c520d0d3b1c838d13a40c19fee9 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 17:05:43 -0300 Subject: [PATCH 09/52] Make traceback non-optional --- src/vm/errors/vm_exception.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 0f09378fa0..1a42649ca3 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -22,7 +22,6 @@ impl VmException { runner: &CairoRunner, vm: &VirtualMachine, error: VirtualMachineError, - with_traceback: bool, ) -> Self { let error_attr_value = get_error_attr_value(vm.run_context.pc.offset, runner); VmException { @@ -30,7 +29,7 @@ impl VmException { inst_location: get_location(vm.run_context.pc.offset, runner), inner_exc: error, error_attr_value, - traceback: with_traceback.then(|| get_traceback(vm, runner)).flatten(), + traceback: get_traceback(vm, runner), } } } @@ -148,12 +147,7 @@ mod test { traceback: None, }; assert_eq!( - VmException::from_vm_error( - &runner, - &vm!(), - VirtualMachineError::CouldntPopPositions, - false - ), + VmException::from_vm_error(&runner, &vm!(), VirtualMachineError::CouldntPopPositions,), vm_excep ) } From e72dff535c6ef48c96f1fca09ba92d8e7056bf43 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 18:04:16 -0300 Subject: [PATCH 10/52] Add tests for is_call_instruction --- src/types/instruction.rs | 18 ++++++++++++++++++ src/vm/errors/vm_exception.rs | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index 5c98e94f3c..2a4a58beed 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -98,3 +98,21 @@ pub(crate) fn is_call_instruction(encoded_instruction: &BigInt, imm: Option Date: Thu, 22 Dec 2022 18:09:58 -0300 Subject: [PATCH 11/52] Add traceback to error display --- src/vm/errors/vm_exception.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 8c1bb9cc57..08ca153117 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -97,6 +97,9 @@ impl Display for VmException { } else { error_msg.push_str(&format!("{}\n", message)); } + if let Some(ref string) = self.traceback { + error_msg.push_str(&format!("{}\n", string)); + } // Write error message write!(f, "{}", error_msg) } From 67ccc395ec0e361dcd4cf7ab3bb1dcb3b559c6d1 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 18:45:01 -0300 Subject: [PATCH 12/52] Add test + fix logic for get_traceback_entries --- src/vm/vm_core.rs | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index d9b075fb9f..d206b9a370 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -743,12 +743,21 @@ impl VirtualMachine { // Fetch the fp and pc traceback entries for _ in 0..MAX_TRACEBACK_ENTRIES { // First we get the fp traceback - match fp.sub(2).ok().map(|ref r| self.memory.get_relocatable(r)) { + let initial_fp = fp; + match initial_fp + .sub(2) + .ok() + .map(|ref r| self.memory.get_relocatable(r)) + { Some(Ok(opt_fp)) if opt_fp != fp => fp = opt_fp, _ => break, } // Then we get the pc traceback - let ret_pc = match fp.sub(1).ok().map(|ref r| self.memory.get_relocatable(r)) { + let ret_pc = match initial_fp + .sub(1) + .ok() + .map(|ref r| self.memory.get_relocatable(r)) + { Some(Ok(opt_pc)) => opt_pc, _ => break, }; @@ -765,7 +774,7 @@ impl VirtualMachine { &instruction0, Some(instruction1.into_owned()), ) { - true => ret_pc.sub(1).unwrap(), // This unwrap wont fail as it is checked before + true => ret_pc.sub(2).unwrap(), // This unwrap wont fail as it is checked before false => break, } } @@ -1005,6 +1014,7 @@ mod tests { bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef, }, instruction::{Op1Addr, Register}, + program::Program, relocatable::Relocatable, }, utils::test_utils::*, @@ -1015,8 +1025,9 @@ mod tests { }; use crate::bigint; + use crate::vm::runners::cairo_runner::CairoRunner; use num_bigint::Sign; - use std::collections::HashSet; + use std::{collections::HashSet, path::Path}; from_bigint_str![18, 75, 76]; @@ -3906,4 +3917,28 @@ mod tests { assert_eq!(vm.compute_effective_sizes(), &vec![4]); } + + #[test] + fn get_traceback_entries_bad_usort() { + let program = Program::from_file( + Path::new("cairo_programs/bad_programs/bad_usort.json"), + Some("main"), + ) + .expect("Call to `Program::from_file()` failed."); + + let hint_processor = BuiltinHintProcessor::new_empty(); + let mut cairo_runner = cairo_runner!(program, "all", false); + let mut vm = vm!(); + + let end = cairo_runner.initialize(&mut vm).unwrap(); + assert!(cairo_runner + .run_until_pc(end, &mut vm, &hint_processor) + .is_err()); + let expected_traceback = vec![ + (Relocatable::from((1, 3)), Relocatable::from((0, 97))), + (Relocatable::from((1, 14)), Relocatable::from((0, 30))), + (Relocatable::from((1, 26)), Relocatable::from((0, 60))), + ]; + assert_eq!(vm.get_traceback_entries(), expected_traceback); + } } From ba410b00c01b1e0032504e53c75416db952bec9a Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 18:48:12 -0300 Subject: [PATCH 13/52] Code refactor --- src/vm/vm_core.rs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index d206b9a370..813b3e65d6 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -742,25 +742,16 @@ impl VirtualMachine { let mut fp = Relocatable::from((1, self.run_context.fp)); // Fetch the fp and pc traceback entries for _ in 0..MAX_TRACEBACK_ENTRIES { - // First we get the fp traceback - let initial_fp = fp; - match initial_fp - .sub(2) - .ok() - .map(|ref r| self.memory.get_relocatable(r)) - { - Some(Ok(opt_fp)) if opt_fp != fp => fp = opt_fp, - _ => break, - } - // Then we get the pc traceback - let ret_pc = match initial_fp - .sub(1) - .ok() - .map(|ref r| self.memory.get_relocatable(r)) - { + // Get return pc + let ret_pc = match fp.sub(1).ok().map(|ref r| self.memory.get_relocatable(r)) { Some(Ok(opt_pc)) => opt_pc, _ => break, }; + // Get fp traceback + match fp.sub(2).ok().map(|ref r| self.memory.get_relocatable(r)) { + Some(Ok(opt_fp)) if opt_fp != fp => fp = opt_fp, + _ => break, + } // Try to check if the call instruction is (instruction0, instruction1) or just // instruction1 (with no immediate). let call_pc = match ret_pc.sub(1).ok().map(|ref r| self.memory.get_integer(r)) { From acf3299cc1ccd62d499a4edc42b2dcc39ac8c254 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 18:50:40 -0300 Subject: [PATCH 14/52] Add one more test for get_traceback_entries --- src/vm/vm_core.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 813b3e65d6..8979f2bfbe 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -3932,4 +3932,24 @@ mod tests { ]; assert_eq!(vm.get_traceback_entries(), expected_traceback); } + + #[test] + fn get_traceback_entries_bad_dict_update() { + let program = Program::from_file( + Path::new("cairo_programs/bad_programs/bad_dict_update.json"), + Some("main"), + ) + .expect("Call to `Program::from_file()` failed."); + + let hint_processor = BuiltinHintProcessor::new_empty(); + let mut cairo_runner = cairo_runner!(program, "all", false); + let mut vm = vm!(); + + let end = cairo_runner.initialize(&mut vm).unwrap(); + assert!(cairo_runner + .run_until_pc(end, &mut vm, &hint_processor) + .is_err()); + let expected_traceback = vec![(Relocatable::from((1, 2)), Relocatable::from((0, 34)))]; + assert_eq!(vm.get_traceback_entries(), expected_traceback); + } } From bc66d0f018266f574f739814984db9e90097a5f8 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 22 Dec 2022 19:12:00 -0300 Subject: [PATCH 15/52] Fix string format + add test for get_traceback --- src/vm/errors/vm_exception.rs | 68 +++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 08ca153117..09fdb79f63 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -61,10 +61,12 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option { - traceback.push_str(&location.to_string(&format!("(pc={})\n", traceback_pc.offset))) - } - None => traceback.push_str(&format!("Unknown location (pc={})\n", traceback_pc.offset)), + Some(location) => traceback + .push_str(&location.to_string(&format!("(pc=0:{})\n", traceback_pc.offset))), + None => traceback.push_str(&format!( + "Unknown location (pc=0:{})\n", + traceback_pc.offset + )), } } (!traceback.is_empty()) @@ -74,7 +76,7 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option fmt::Result { // Build initial message - let message = format!("Error at pc={}:\n{}", self.pc, self.inner_exc); + let message = format!("Error at pc=0:{}:\n{}", self.pc, self.inner_exc); let mut error_msg = String::new(); // Add error attribute value if let Some(ref string) = self.error_attr_value { @@ -108,7 +110,7 @@ impl Display for VmException { impl Location { /// Prints the location with the passed message. pub fn to_string(&self, message: &String) -> String { - let msg_prefix = if message.is_empty() { "" } else { ":" }; + let msg_prefix = if message.is_empty() { "" } else { ": " }; format!( "{}:{}:{}{}{}", self.input_file.filename, self.start_line, self.start_col, msg_prefix, message @@ -119,7 +121,9 @@ impl Location { mod test { use num_bigint::{BigInt, Sign}; use std::collections::HashMap; + use std::path::Path; + use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; use crate::serde::deserialize_program::{Attribute, InputFile}; use crate::types::program::Program; use crate::types::relocatable::Relocatable; @@ -189,7 +193,7 @@ mod test { let message = String::from("While expanding the reference"); assert_eq!( location.to_string(&message), - String::from("Folder/file.cairo:1:1:While expanding the reference") + String::from("Folder/file.cairo:1:1: While expanding the reference") ) } @@ -208,7 +212,7 @@ mod test { assert_eq!( vm_excep.to_string(), format!( - "Error at pc=2:\n{}\n", + "Error at pc=0:2:\n{}\n", VirtualMachineError::FailedToComputeOperands( "op0".to_string(), Relocatable::from((0, 4)) @@ -232,7 +236,7 @@ mod test { assert_eq!( vm_excep.to_string(), format!( - "Error message: Block may fail\nError at pc=2:\n{}\n", + "Error message: Block may fail\nError at pc=0:2:\n{}\n", VirtualMachineError::FailedToComputeOperands( "op0".to_string(), Relocatable::from((0, 4)) @@ -266,7 +270,7 @@ mod test { assert_eq!( vm_excep.to_string(), format!( - "Folder/file.cairo:1:1:Error at pc=2:\n{}\n", + "Folder/file.cairo:1:1: Error at pc=0:2:\n{}\n", VirtualMachineError::FailedToComputeOperands( "op0".to_string(), Relocatable::from((0, 4)) @@ -312,7 +316,7 @@ mod test { assert_eq!( vm_excep.to_string(), format!( - "Folder/file_b.cairo:2:2:While expanding the reference:\nFolder/file.cairo:1:1:Error at pc=2:\n{}\n", + "Folder/file_b.cairo:2:2: While expanding the reference:\nFolder/file.cairo:1:1: Error at pc=0:2:\n{}\n", VirtualMachineError::FailedToComputeOperands("op0".to_string(), Relocatable::from((0, 4))) ) ) @@ -381,4 +385,46 @@ mod test { let runner = cairo_runner!(program); assert_eq!(get_location(3, &runner), None); } + + #[test] + // TEST CASE WITHOUT FILE CONTENTS + fn get_traceback_bad_dict_update() { + let program = Program::from_file( + Path::new("cairo_programs/bad_programs/bad_dict_update.json"), + Some("main"), + ) + .expect("Call to `Program::from_file()` failed."); + + let hint_processor = BuiltinHintProcessor::new_empty(); + let mut cairo_runner = cairo_runner!(program, "all", false); + let mut vm = vm!(); + + let end = cairo_runner.initialize(&mut vm).unwrap(); + assert!(cairo_runner + .run_until_pc(end, &mut vm, &hint_processor) + .is_err()); + let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_dict_update.cairo:10:5: (pc=0:34)\n"); + assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); + } + + #[test] + // TEST CASE WITHOUT FILE CONTENTS + fn get_traceback_bad_usort() { + let program = Program::from_file( + Path::new("cairo_programs/bad_programs/bad_usort.json"), + Some("main"), + ) + .expect("Call to `Program::from_file()` failed."); + + let hint_processor = BuiltinHintProcessor::new_empty(); + let mut cairo_runner = cairo_runner!(program, "all", false); + let mut vm = vm!(); + + let end = cairo_runner.initialize(&mut vm).unwrap(); + assert!(cairo_runner + .run_until_pc(end, &mut vm, &hint_processor) + .is_err()); + let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_usort.cairo:91:48: (pc=0:97)\ncairo_programs/bad_programs/bad_usort.cairo:36:5: (pc=0:30)\ncairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)\n"); + assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); + } } From b3952cb08febb6b2e369522d9323ff3de438783d Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 11:26:26 -0300 Subject: [PATCH 16/52] Improve fn --- src/vm/errors/vm_exception.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 09fdb79f63..b0ff1b1d92 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -23,10 +23,11 @@ impl VmException { vm: &VirtualMachine, error: VirtualMachineError, ) -> Self { - let error_attr_value = get_error_attr_value(vm.run_context.pc.offset, runner); + let pc = vm.run_context.pc.offset; + let error_attr_value = get_error_attr_value(pc, runner); VmException { - pc: vm.run_context.pc.offset, - inst_location: get_location(vm.run_context.pc.offset, runner), + pc, + inst_location: get_location(pc, runner), inner_exc: error, error_attr_value, traceback: get_traceback(vm, runner), From c2fa8a0f0f8e5f4b8f8427b59eb3a5a29e9571bb Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 11:31:56 -0300 Subject: [PATCH 17/52] Add reference to is_call_instruction signature --- src/types/instruction.rs | 6 +++--- src/vm/vm_core.rs | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index 2a4a58beed..152fee1a52 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -83,12 +83,12 @@ impl Instruction { } // Returns True if the given instruction looks like a call instruction. -pub(crate) fn is_call_instruction(encoded_instruction: &BigInt, imm: Option) -> bool { +pub(crate) fn is_call_instruction(encoded_instruction: &BigInt, imm: Option<&BigInt>) -> bool { let encoded_i64_instruction: i64 = match encoded_instruction.to_i64() { Some(num) => num, None => return false, }; - let instruction = match decode_instruction(encoded_i64_instruction, imm) { + let instruction = match decode_instruction(encoded_i64_instruction, imm.cloned()) { Ok(inst) => inst, Err(_) => return false, }; @@ -108,7 +108,7 @@ mod tests { #[test] fn is_call_instruction_true() { let encoded_instruction = bigint!(1226245742482522112_i64); - assert!(is_call_instruction(&encoded_instruction, Some(bigint!(2)))); + assert!(is_call_instruction(&encoded_instruction, Some(&bigint!(2)))); } #[test] fn is_call_instruction_false() { diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 8979f2bfbe..9cea35ce4d 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -761,10 +761,7 @@ impl VirtualMachine { false => { match ret_pc.sub(2).ok().map(|ref r| self.memory.get_integer(r)) { Some(Ok(instruction0)) => { - match is_call_instruction( - &instruction0, - Some(instruction1.into_owned()), - ) { + match is_call_instruction(&instruction0, Some(&instruction1)) { true => ret_pc.sub(2).unwrap(), // This unwrap wont fail as it is checked before false => break, } From 88e4b528d47ccfa1040d97cda4eb0de6803cf88e Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 11:39:51 -0300 Subject: [PATCH 18/52] Add reference to immediate in decode_instruction + remove clone --- src/types/instruction.rs | 2 +- src/vm/decoding/decoder.rs | 6 +++--- src/vm/trace/mod.rs | 2 +- src/vm/vm_core.rs | 3 +-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/types/instruction.rs b/src/types/instruction.rs index 152fee1a52..aec88a4de1 100644 --- a/src/types/instruction.rs +++ b/src/types/instruction.rs @@ -88,7 +88,7 @@ pub(crate) fn is_call_instruction(encoded_instruction: &BigInt, imm: Option<&Big Some(num) => num, None => return false, }; - let instruction = match decode_instruction(encoded_i64_instruction, imm.cloned()) { + let instruction = match decode_instruction(encoded_i64_instruction, imm) { Ok(inst) => inst, Err(_) => return false, }; diff --git a/src/vm/decoding/decoder.rs b/src/vm/decoding/decoder.rs index 432aeda40e..33d0274605 100644 --- a/src/vm/decoding/decoder.rs +++ b/src/vm/decoding/decoder.rs @@ -7,7 +7,7 @@ use num_bigint::BigInt; /// Decodes an instruction. The encoding is little endian, so flags go from bit 63 to 48. pub fn decode_instruction( encoded_instr: i64, - mut imm: Option, + mut imm: Option<&BigInt>, ) -> Result { const DST_REG_MASK: i64 = 0x0001; const DST_REG_OFF: i64 = 0; @@ -118,7 +118,7 @@ pub fn decode_instruction( off0, off1, off2, - imm, + imm: imm.cloned(), dst_register, op0_register, op1_addr, @@ -197,7 +197,7 @@ mod decoder_test { // | CALL| ADD| JUMP| ADD| IMM| FP| FP // 0 0 0 1 0 1 0 0 1 0 1 0 0 1 1 1 // 0001 0100 1010 0111 = 0x14A7; offx = 0 - let inst = decode_instruction(0x14A7800080008000, Some(bigint!(7))).unwrap(); + let inst = decode_instruction(0x14A7800080008000, Some(&bigint!(7))).unwrap(); assert!(matches!(inst.dst_register, instruction::Register::FP)); assert!(matches!(inst.op0_register, instruction::Register::FP)); assert!(matches!(inst.op1_addr, instruction::Op1Addr::Imm)); diff --git a/src/vm/trace/mod.rs b/src/vm/trace/mod.rs index aa60d6da4e..26a0130cc5 100644 --- a/src/vm/trace/mod.rs +++ b/src/vm/trace/mod.rs @@ -34,7 +34,7 @@ pub fn get_perm_range_check_limits( }) .transpose()?; - let decoded_instruction = decode_instruction(instruction, immediate)?; + let decoded_instruction = decode_instruction(instruction, immediate.as_ref())?; let off0 = decoded_instruction .off0 .to_isize() diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 9cea35ce4d..1c09f2973c 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -507,8 +507,7 @@ impl VirtualMachine { match instruction_ref.to_i64() { Some(instruction) => { if let Some(MaybeRelocatable::Int(imm_ref)) = imm.as_ref().map(|x| x.as_ref()) { - let decoded_instruction = - decode_instruction(instruction, Some(imm_ref.clone()))?; + let decoded_instruction = decode_instruction(instruction, Some(imm_ref))?; return Ok(decoded_instruction); } let decoded_instruction = decode_instruction(instruction, None)?; From 371dc43dcc2605725734514ee37db4404054f44f Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 11:48:33 -0300 Subject: [PATCH 19/52] Fix hint_processor mutability in tests --- src/vm/errors/vm_exception.rs | 8 ++++---- src/vm/vm_core.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index b0ff1b1d92..820c95caeb 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -396,13 +396,13 @@ mod test { ) .expect("Call to `Program::from_file()` failed."); - let hint_processor = BuiltinHintProcessor::new_empty(); + let mut hint_processor = BuiltinHintProcessor::new_empty(); let mut cairo_runner = cairo_runner!(program, "all", false); let mut vm = vm!(); let end = cairo_runner.initialize(&mut vm).unwrap(); assert!(cairo_runner - .run_until_pc(end, &mut vm, &hint_processor) + .run_until_pc(end, &mut vm, &mut hint_processor) .is_err()); let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_dict_update.cairo:10:5: (pc=0:34)\n"); assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); @@ -417,13 +417,13 @@ mod test { ) .expect("Call to `Program::from_file()` failed."); - let hint_processor = BuiltinHintProcessor::new_empty(); + let mut hint_processor = BuiltinHintProcessor::new_empty(); let mut cairo_runner = cairo_runner!(program, "all", false); let mut vm = vm!(); let end = cairo_runner.initialize(&mut vm).unwrap(); assert!(cairo_runner - .run_until_pc(end, &mut vm, &hint_processor) + .run_until_pc(end, &mut vm, &mut hint_processor) .is_err()); let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_usort.cairo:91:48: (pc=0:97)\ncairo_programs/bad_programs/bad_usort.cairo:36:5: (pc=0:30)\ncairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)\n"); assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 5bc683f811..2b073c9191 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -3913,13 +3913,13 @@ mod tests { ) .expect("Call to `Program::from_file()` failed."); - let hint_processor = BuiltinHintProcessor::new_empty(); + let mut hint_processor = BuiltinHintProcessor::new_empty(); let mut cairo_runner = cairo_runner!(program, "all", false); let mut vm = vm!(); let end = cairo_runner.initialize(&mut vm).unwrap(); assert!(cairo_runner - .run_until_pc(end, &mut vm, &hint_processor) + .run_until_pc(end, &mut vm, &mut hint_processor) .is_err()); let expected_traceback = vec![ (Relocatable::from((1, 3)), Relocatable::from((0, 97))), @@ -3937,13 +3937,13 @@ mod tests { ) .expect("Call to `Program::from_file()` failed."); - let hint_processor = BuiltinHintProcessor::new_empty(); + let mut hint_processor = BuiltinHintProcessor::new_empty(); let mut cairo_runner = cairo_runner!(program, "all", false); let mut vm = vm!(); let end = cairo_runner.initialize(&mut vm).unwrap(); assert!(cairo_runner - .run_until_pc(end, &mut vm, &hint_processor) + .run_until_pc(end, &mut vm, &mut hint_processor) .is_err()); let expected_traceback = vec![(Relocatable::from((1, 2)), Relocatable::from((0, 34)))]; assert_eq!(vm.get_traceback_entries(), expected_traceback); From 46a72027162253358f1859de3794df563bd13728 Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 18:50:42 -0300 Subject: [PATCH 20/52] Add Location::get_location_marks --- src/vm/errors/vm_exception.rs | 38 ++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 820c95caeb..753da0857d 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -1,4 +1,8 @@ -use std::fmt::{self, Display}; +use std::{ + fmt::{self, Display}, + io::Read, + path::Path, +}; use thiserror::Error; @@ -117,6 +121,38 @@ impl Location { self.input_file.filename, self.start_line, self.start_col, msg_prefix, message ) } + + pub fn to_string_with_content(&self, message: &String) -> String { + let string = self.to_string(message); + let _file_contents = Path::new(&self.input_file.filename); + string + } + + pub fn get_location_marks(&self, file_contents: &mut impl Read) -> String { + let mut contents = String::new(); + // If this read fails, the string will be left empty, so we can ignore the result + let _ = file_contents.read_to_string(&mut contents); + let split_lines: Vec<&str> = contents.rsplit('\n').collect(); + if !(0 < self.start_line && ((self.start_line - 1) as usize) < split_lines.len()) { + return String::new(); + } + let start_line = split_lines[((self.start_line - 1) as usize)]; + let start_col = self.start_col as usize; + let mut result = format!("{}\n", start_line); + let end_col = if self.start_line == self.end_line { + self.end_col as usize + } else { + start_line.len() + 1 + }; + let left_margin: String = vec![' '; start_col - 1].into_iter().collect(); + if end_col > start_col + 1 { + let highlight: String = vec!['*'; end_col - start_col - 2].into_iter().collect(); + result.push_str(&format!("{}^{}^", left_margin, highlight)); + } else { + result.push_str(&format!("{}^", left_margin)) + } + result + } } #[cfg(test)] mod test { From fd0b9c6c5fbb8fcdf913e07d5c8658fbf3eee9c9 Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 19:04:21 -0300 Subject: [PATCH 21/52] Fix method to_string_with_contents --- src/vm/errors/vm_exception.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 753da0857d..144fe19af4 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -1,6 +1,7 @@ use std::{ fmt::{self, Display}, - io::Read, + fs::File, + io::{BufReader, Read}, path::Path, }; @@ -123,8 +124,12 @@ impl Location { } pub fn to_string_with_content(&self, message: &String) -> String { - let string = self.to_string(message); - let _file_contents = Path::new(&self.input_file.filename); + let mut string = self.to_string(message); + let input_file_path = Path::new(&self.input_file.filename); + if let Ok(file) = File::open(input_file_path) { + let mut reader = BufReader::new(file); + string.push_str(&format!("\n{}", self.get_location_marks(&mut reader))); + } string } From 5e753bbad18cfcd0183d929d450cb426abe6b31d Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 27 Dec 2022 19:26:27 -0300 Subject: [PATCH 22/52] Fix string format --- src/vm/errors/vm_exception.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 144fe19af4..84f6bbf999 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -67,8 +67,9 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option traceback - .push_str(&location.to_string(&format!("(pc=0:{})\n", traceback_pc.offset))), + Some(location) => traceback.push_str( + &location.to_string_with_content(&format!("(pc=0:{})\n", traceback_pc.offset)), + ), None => traceback.push_str(&format!( "Unknown location (pc=0:{})\n", traceback_pc.offset @@ -128,7 +129,7 @@ impl Location { let input_file_path = Path::new(&self.input_file.filename); if let Ok(file) = File::open(input_file_path) { let mut reader = BufReader::new(file); - string.push_str(&format!("\n{}", self.get_location_marks(&mut reader))); + string.push_str(&format!("{}", self.get_location_marks(&mut reader))); } string } @@ -137,7 +138,7 @@ impl Location { let mut contents = String::new(); // If this read fails, the string will be left empty, so we can ignore the result let _ = file_contents.read_to_string(&mut contents); - let split_lines: Vec<&str> = contents.rsplit('\n').collect(); + let split_lines: Vec<&str> = contents.split('\n').collect(); if !(0 < self.start_line && ((self.start_line - 1) as usize) < split_lines.len()) { return String::new(); } @@ -152,9 +153,9 @@ impl Location { let left_margin: String = vec![' '; start_col - 1].into_iter().collect(); if end_col > start_col + 1 { let highlight: String = vec!['*'; end_col - start_col - 2].into_iter().collect(); - result.push_str(&format!("{}^{}^", left_margin, highlight)); + result.push_str(&format!("{}^{}^\n", left_margin, highlight)); } else { - result.push_str(&format!("{}^", left_margin)) + result.push_str(&format!("{}^\n", left_margin)) } result } From 09ee59606fee42a31988cb7334d765e55babd542 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 14:06:15 -0300 Subject: [PATCH 23/52] Fix string format --- src/vm/errors/vm_exception.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 84f6bbf999..08921615c8 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -129,7 +129,7 @@ impl Location { let input_file_path = Path::new(&self.input_file.filename); if let Ok(file) = File::open(input_file_path) { let mut reader = BufReader::new(file); - string.push_str(&format!("{}", self.get_location_marks(&mut reader))); + string.push_str(&format!("{}\n", self.get_location_marks(&mut reader))); } string } @@ -153,9 +153,9 @@ impl Location { let left_margin: String = vec![' '; start_col - 1].into_iter().collect(); if end_col > start_col + 1 { let highlight: String = vec!['*'; end_col - start_col - 2].into_iter().collect(); - result.push_str(&format!("{}^{}^\n", left_margin, highlight)); + result.push_str(&format!("{}^{}^", left_margin, highlight)); } else { - result.push_str(&format!("{}^\n", left_margin)) + result.push_str(&format!("{}^", left_margin)) } result } From 9eac613055f16a30109a344b411cfbc6eb888ec5 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 14:14:17 -0300 Subject: [PATCH 24/52] Update traceback tests --- src/vm/errors/vm_exception.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 08921615c8..e248525533 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -430,7 +430,6 @@ mod test { } #[test] - // TEST CASE WITHOUT FILE CONTENTS fn get_traceback_bad_dict_update() { let program = Program::from_file( Path::new("cairo_programs/bad_programs/bad_dict_update.json"), @@ -446,12 +445,11 @@ mod test { assert!(cairo_runner .run_until_pc(end, &mut vm, &mut hint_processor) .is_err()); - let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_dict_update.cairo:10:5: (pc=0:34)\n"); + let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_dict_update.cairo:10:5: (pc=0:34)\n dict_update{dict_ptr=my_dict}(key=2, prev_value=3, new_value=4);\n ^*************************************************************^\n"); assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); } #[test] - // TEST CASE WITHOUT FILE CONTENTS fn get_traceback_bad_usort() { let program = Program::from_file( Path::new("cairo_programs/bad_programs/bad_usort.json"), @@ -467,7 +465,7 @@ mod test { assert!(cairo_runner .run_until_pc(end, &mut vm, &mut hint_processor) .is_err()); - let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_usort.cairo:91:48: (pc=0:97)\ncairo_programs/bad_programs/bad_usort.cairo:36:5: (pc=0:30)\ncairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)\n"); + let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_usort.cairo:91:48: (pc=0:97)\n let (output_len, output, multiplicities) = usort(input_len=3, input=input_array);\n ^***********************************^\ncairo_programs/bad_programs/bad_usort.cairo:36:5: (pc=0:30)\n verify_usort{output=output}(\n ^**************************^\ncairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)\n verify_multiplicity(multiplicity=multiplicity, input_len=input_len, input=input, value=value);\n ^*******************************************************************************************^\n"); assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); } } From 3612b01a6a005f9a77be8ea9b9535108a74aabf6 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 14:55:39 -0300 Subject: [PATCH 25/52] Add tests for Location::to_string_with_contents() --- src/vm/errors/vm_exception.rs | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index e248525533..aaba596e92 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -468,4 +468,42 @@ mod test { let expected_traceback = String::from("Cairo traceback (most recent call last):\ncairo_programs/bad_programs/bad_usort.cairo:91:48: (pc=0:97)\n let (output_len, output, multiplicities) = usort(input_len=3, input=input_array);\n ^***********************************^\ncairo_programs/bad_programs/bad_usort.cairo:36:5: (pc=0:30)\n verify_usort{output=output}(\n ^**************************^\ncairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)\n verify_multiplicity(multiplicity=multiplicity, input_len=input_len, input=input, value=value);\n ^*******************************************************************************************^\n"); assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback)); } + + #[test] + fn location_to_string_with_contents_no_contents() { + let location = Location { + end_line: 2, + end_col: 2, + input_file: InputFile { + filename: String::from("Folder/file.cairo"), + }, + parent_location: None, + start_line: 1, + start_col: 1, + }; + let message = String::from("While expanding the reference"); + assert_eq!( + location.to_string_with_content(&message), + String::from("Folder/file.cairo:1:1: While expanding the reference") + ) + } + + #[test] + fn location_to_string_with_contents() { + let location = Location { + end_line: 5, + end_col: 2, + input_file: InputFile { + filename: String::from("cairo_programs/bad_programs/bad_usort.cairo"), + }, + parent_location: None, + start_line: 5, + start_col: 1, + }; + let message = String::from("Error at pc=0:75:\n"); + assert_eq!( + location.to_string_with_content(&message), + String::from("cairo_programs/bad_programs/bad_usort.cairo:5:1: Error at pc=0:75:\nfunc usort{range_check_ptr}(input_len: felt, input: felt*) -> (\n^\n") + ) + } } From f56122d32cbbbd4a78e666405b785cdeff689f1f Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 15:05:06 -0300 Subject: [PATCH 26/52] Fix intermediate string format --- src/vm/errors/vm_exception.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index aaba596e92..4ce744b8a1 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -67,9 +67,10 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option traceback.push_str( - &location.to_string_with_content(&format!("(pc=0:{})\n", traceback_pc.offset)), - ), + Some(location) => traceback.push_str(&format!( + "{}\n", + location.to_string_with_content(&format!("(pc=0:{})\n", traceback_pc.offset)) + )), None => traceback.push_str(&format!( "Unknown location (pc=0:{})\n", traceback_pc.offset @@ -129,7 +130,7 @@ impl Location { let input_file_path = Path::new(&self.input_file.filename); if let Ok(file) = File::open(input_file_path) { let mut reader = BufReader::new(file); - string.push_str(&format!("{}\n", self.get_location_marks(&mut reader))); + string.push_str(&self.get_location_marks(&mut reader)); } string } From 00ccd31202f6671fbe8c534e4602ccf440317c64 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 15:18:41 -0300 Subject: [PATCH 27/52] Fix test --- src/vm/errors/vm_exception.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 4ce744b8a1..2e4c5946c7 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -504,7 +504,7 @@ mod test { let message = String::from("Error at pc=0:75:\n"); assert_eq!( location.to_string_with_content(&message), - String::from("cairo_programs/bad_programs/bad_usort.cairo:5:1: Error at pc=0:75:\nfunc usort{range_check_ptr}(input_len: felt, input: felt*) -> (\n^\n") + String::from("cairo_programs/bad_programs/bad_usort.cairo:5:1: Error at pc=0:75:\nfunc usort{range_check_ptr}(input_len: felt, input: felt*) -> (\n^") ) } } From 2ed228760887c23af413f85d9ed22949fcda54b6 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 15:37:29 -0300 Subject: [PATCH 28/52] Add tests for Location::get_location_marks() --- src/vm/errors/vm_exception.rs | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 2e4c5946c7..742d4dc591 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -507,4 +507,62 @@ mod test { String::from("cairo_programs/bad_programs/bad_usort.cairo:5:1: Error at pc=0:75:\nfunc usort{range_check_ptr}(input_len: felt, input: felt*) -> (\n^") ) } + + #[test] + fn location_to_string_with_contents_no_file() { + let location = Location { + end_line: 5, + end_col: 2, + input_file: InputFile { + filename: String::from("cairo_programs/bad_prtypoograms/bad_usort.cairo"), + }, + parent_location: None, + start_line: 5, + start_col: 1, + }; + let message = String::from("Error at pc=0:75:\n"); + assert_eq!( + location.to_string_with_content(&message), + String::from( + "cairo_programs/bad_prtypoograms/bad_usort.cairo:5:1: Error at pc=0:75:\n" + ) + ) + } + + #[test] + fn location_get_location_marks() { + let location = Location { + end_line: 5, + end_col: 2, + input_file: InputFile { + filename: String::from("cairo_programs/bad_programs/bad_usort.cairo"), + }, + parent_location: None, + start_line: 5, + start_col: 1, + }; + let input_file_path = Path::new(&location.input_file.filename); + let file = File::open(input_file_path).expect("Failed to open file"); + let mut reader = BufReader::new(file); + assert_eq!( + location.get_location_marks(&mut reader), + String::from("func usort{range_check_ptr}(input_len: felt, input: felt*) -> (\n^") + ) + } + + #[test] + fn location_get_location_marks_empty_file() { + let location = Location { + end_line: 5, + end_col: 2, + input_file: InputFile { + filename: String::from("cairo_programs/bad_programs/bad_usort.cairo"), + }, + parent_location: None, + start_line: 5, + start_col: 1, + }; + let mut reader: &[u8] = &[]; + assert_eq!(location.get_location_marks(&mut reader), String::from("")) + } } From 839cbf1ff53fbcc0efce8aaf4dcbe90dd3c6036f Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 16:00:25 -0300 Subject: [PATCH 29/52] Update VmException display --- src/vm/errors/vm_exception.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 742d4dc591..75c89bf6a3 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -84,7 +84,7 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option fmt::Result { // Build initial message - let message = format!("Error at pc=0:{}:\n{}", self.pc, self.inner_exc); + let message = format!("Error at pc=0:{}:\n{}\n", self.pc, self.inner_exc); let mut error_msg = String::new(); // Add error attribute value if let Some(ref string) = self.error_attr_value { @@ -95,7 +95,11 @@ impl Display for VmException { let mut location_msg = String::new(); let (mut location, mut message) = (location, &message); loop { - location_msg = format!("{}\n{}", location.to_string(message), location_msg); + location_msg = format!( + "{}\n{}", + location.to_string_with_content(message), + location_msg + ); // Add parent location info if let Some(parent) = &location.parent_location { (location, message) = (&parent.0, &parent.1) From 8937c87f5da88553a7d935ee294657f003996d3d Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 16:02:04 -0300 Subject: [PATCH 30/52] Fix string format --- src/vm/errors/vm_exception.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 75c89bf6a3..c335d7c1c8 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -109,7 +109,7 @@ impl Display for VmException { } error_msg.push_str(&location_msg) } else { - error_msg.push_str(&format!("{}\n", message)); + error_msg.push_str(&format!("{}", message)); } if let Some(ref string) = self.traceback { error_msg.push_str(&format!("{}\n", string)); From 747bb7797e47a9dcbbd1f1dac0ce48f448faea0a Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 16:12:23 -0300 Subject: [PATCH 31/52] Fix string format --- src/vm/errors/vm_exception.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index c335d7c1c8..bb6ebfebd2 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -84,7 +84,7 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option fmt::Result { // Build initial message - let message = format!("Error at pc=0:{}:\n{}\n", self.pc, self.inner_exc); + let message = format!("Error at pc=0:{}:\n{}", self.pc, self.inner_exc); let mut error_msg = String::new(); // Add error attribute value if let Some(ref string) = self.error_attr_value { @@ -96,8 +96,8 @@ impl Display for VmException { let (mut location, mut message) = (location, &message); loop { location_msg = format!( - "{}\n{}", - location.to_string_with_content(message), + "{}{}", + location.to_string_with_content(&format!("{}\n", message)), location_msg ); // Add parent location info @@ -109,7 +109,7 @@ impl Display for VmException { } error_msg.push_str(&location_msg) } else { - error_msg.push_str(&format!("{}", message)); + error_msg.push_str(&format!("{}\n", message)); } if let Some(ref string) = self.traceback { error_msg.push_str(&format!("{}\n", string)); From 5f78c476748fcfa0c843bd4402759c2298999677 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 16:23:19 -0300 Subject: [PATCH 32/52] Remove debug print --- src/main.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index d8a8a62d16..f8e963fb8f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,10 +57,7 @@ fn main() -> Result<(), CairoRunError> { &mut hint_executor, ) { Ok(runner) => runner, - Err(error) => { - println!("{}", error); - return Err(error); - } + Err(error) => return Err(error), }; if let Some(trace_path) = args.trace_file { From 542e06ef482e1fdcb8988cf64fb4d53879fdf2a2 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 17:42:53 -0300 Subject: [PATCH 33/52] Fix Display --- src/vm/errors/vm_exception.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index bb6ebfebd2..3a8babd97d 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -69,12 +69,9 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option traceback.push_str(&format!( "{}\n", - location.to_string_with_content(&format!("(pc=0:{})\n", traceback_pc.offset)) - )), - None => traceback.push_str(&format!( - "Unknown location (pc=0:{})\n", - traceback_pc.offset + location.to_string_with_content(&format!("(pc=0:{})", traceback_pc.offset)) )), + None => traceback.push_str(&format!("Unknown location (pc=0:{})", traceback_pc.offset)), } } (!traceback.is_empty()) @@ -96,9 +93,9 @@ impl Display for VmException { let (mut location, mut message) = (location, &message); loop { location_msg = format!( - "{}{}", - location.to_string_with_content(&format!("{}\n", message)), - location_msg + "{}\n{}", + location.to_string_with_content(message), + &location_msg ); // Add parent location info if let Some(parent) = &location.parent_location { @@ -107,7 +104,7 @@ impl Display for VmException { break; } } - error_msg.push_str(&location_msg) + error_msg.push_str(&location_msg); } else { error_msg.push_str(&format!("{}\n", message)); } @@ -134,7 +131,7 @@ impl Location { let input_file_path = Path::new(&self.input_file.filename); if let Ok(file) = File::open(input_file_path) { let mut reader = BufReader::new(file); - string.push_str(&self.get_location_marks(&mut reader)); + string.push_str(&format!("\n{}", self.get_location_marks(&mut reader))); } string } @@ -505,7 +502,7 @@ mod test { start_line: 5, start_col: 1, }; - let message = String::from("Error at pc=0:75:\n"); + let message = String::from("Error at pc=0:75:"); assert_eq!( location.to_string_with_content(&message), String::from("cairo_programs/bad_programs/bad_usort.cairo:5:1: Error at pc=0:75:\nfunc usort{range_check_ptr}(input_len: felt, input: felt*) -> (\n^") From d33f6e1e9a5a8a8f71366b1e17cb2a9fdf7f6acb Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 18:26:32 -0300 Subject: [PATCH 34/52] Implement Display for MaybeRelocatable --- src/types/relocatable.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/types/relocatable.rs b/src/types/relocatable.rs index b9aa8658d1..c42dc91aab 100644 --- a/src/types/relocatable.rs +++ b/src/types/relocatable.rs @@ -5,7 +5,7 @@ use crate::{ use num_bigint::BigInt; use num_integer::Integer; use num_traits::{FromPrimitive, Signed, ToPrimitive}; -use std::ops::Add; +use std::{ops::Add, fmt::{self, Display}}; #[derive(Eq, Hash, PartialEq, PartialOrd, Clone, Copy, Debug)] pub struct Relocatable { @@ -64,6 +64,15 @@ impl From for MaybeRelocatable { } } +impl Display for MaybeRelocatable { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + MaybeRelocatable::RelocatableValue(rel) => write!(f, "{}:{}", rel.segment_index, rel.offset), + MaybeRelocatable::Int(num) => write!(f, "{}", num), + } + } +} + impl Add for Relocatable { type Output = Relocatable; fn add(self, other: usize) -> Self { From 2fdef4af653bbf883cbb2c863976bb033c6ed153 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 18:27:24 -0300 Subject: [PATCH 35/52] Add real-case test for VmException Display --- .../bad_programs/bad_range_check.cairo | 25 +++++++++++ src/types/relocatable.rs | 9 +++- src/vm/errors/vm_errors.rs | 2 +- src/vm/errors/vm_exception.rs | 41 ++++++++++++++++++- 4 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 cairo_programs/bad_programs/bad_range_check.cairo diff --git a/cairo_programs/bad_programs/bad_range_check.cairo b/cairo_programs/bad_programs/bad_range_check.cairo new file mode 100644 index 0000000000..86f6df5ae1 --- /dev/null +++ b/cairo_programs/bad_programs/bad_range_check.cairo @@ -0,0 +1,25 @@ +%builtins range_check + +func check_range{range_check_ptr: felt*}(num: felt) { + with_attr error_message("Failed range-check") { + [range_check_ptr] = num; + } + return(); +} + +func sub_1_check_range{range_check_ptr: felt*}(num: felt) -> felt { + check_range(num - 1); + return num - 1; +} + +func sub_by_1_check_range{range_check_ptr: felt*}(num: felt, sub_amount: felt) { + if (sub_amount == 0) { + return(); + } + return sub_by_1_check_range(sub_1_check_range(num), sub_amount -1); +} + +func main{range_check_ptr: felt*}() { + sub_by_1_check_range(6, 7); + return (); +} diff --git a/src/types/relocatable.rs b/src/types/relocatable.rs index c42dc91aab..a444a4a74b 100644 --- a/src/types/relocatable.rs +++ b/src/types/relocatable.rs @@ -5,7 +5,10 @@ use crate::{ use num_bigint::BigInt; use num_integer::Integer; use num_traits::{FromPrimitive, Signed, ToPrimitive}; -use std::{ops::Add, fmt::{self, Display}}; +use std::{ + fmt::{self, Display}, + ops::Add, +}; #[derive(Eq, Hash, PartialEq, PartialOrd, Clone, Copy, Debug)] pub struct Relocatable { @@ -67,7 +70,9 @@ impl From for MaybeRelocatable { impl Display for MaybeRelocatable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - MaybeRelocatable::RelocatableValue(rel) => write!(f, "{}:{}", rel.segment_index, rel.offset), + MaybeRelocatable::RelocatableValue(rel) => { + write!(f, "{}:{}", rel.segment_index, rel.offset) + } MaybeRelocatable::Int(num) => write!(f, "{}", num), } } diff --git a/src/vm/errors/vm_errors.rs b/src/vm/errors/vm_errors.rs index 9109703efa..da62dfbc62 100644 --- a/src/vm/errors/vm_errors.rs +++ b/src/vm/errors/vm_errors.rs @@ -28,7 +28,7 @@ pub enum VirtualMachineError { UnconstrainedResJumpRel, #[error("Res.UNCONSTRAINED cannot be used with Opcode.ASSERT_EQ")] UnconstrainedResAssertEq, - #[error("ASSERT_EQ instruction failed; {0:?} != {1:?}")] + #[error("An ASSERT_EQ instruction failed: {0} != {1}.")] DiffAssertValues(MaybeRelocatable, MaybeRelocatable), #[error("Call failed to write return-pc (inconsistent op0): {0:?} != {1:?}. Did you forget to increment ap?")] CantWriteReturnPc(MaybeRelocatable, MaybeRelocatable), diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 3a8babd97d..dad7fc5893 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -109,7 +109,7 @@ impl Display for VmException { error_msg.push_str(&format!("{}\n", message)); } if let Some(ref string) = self.traceback { - error_msg.push_str(&format!("{}\n", string)); + error_msg.push_str(&format!("{}", string)); } // Write error message write!(f, "{}", error_msg) @@ -566,4 +566,43 @@ mod test { let mut reader: &[u8] = &[]; assert_eq!(location.get_location_marks(&mut reader), String::from("")) } + + #[test] + fn run_bad_range_check_and_check_error_displayed() { + let expected_error_string = r#"Error message: Failed range-check +cairo_programs/bad_programs/bad_range_check.cairo:5:9: Error at pc=0:0: +An ASSERT_EQ instruction failed: 4 != 5. + [range_check_ptr] = num; + ^*********************^ +Cairo traceback (most recent call last): +cairo_programs/bad_programs/bad_range_check.cairo:23:5: (pc=0:29) + sub_by_1_check_range(6, 7); + ^************************^ +cairo_programs/bad_programs/bad_range_check.cairo:19:12: (pc=0:21) + return sub_by_1_check_range(sub_1_check_range(num), sub_amount -1); + ^*********************************************************^ +cairo_programs/bad_programs/bad_range_check.cairo:19:33: (pc=0:17) + return sub_by_1_check_range(sub_1_check_range(num), sub_amount -1); + ^********************^ +cairo_programs/bad_programs/bad_range_check.cairo:11:5: (pc=0:6) + check_range(num - 1); + ^******************^ +"#; + let program = Program::from_file( + Path::new("cairo_programs/bad_programs/bad_range_check.json"), + Some("main"), + ) + .expect("Call to `Program::from_file()` failed."); + + let mut hint_processor = BuiltinHintProcessor::new_empty(); + let mut cairo_runner = cairo_runner!(program, "all", false); + let mut vm = vm!(); + + let end = cairo_runner.initialize(&mut vm).unwrap(); + let error = cairo_runner + .run_until_pc(end, &mut vm, &mut hint_processor) + .unwrap_err(); + let vm_excepction = VmException::from_vm_error(&cairo_runner, &vm, error); + assert_eq!(vm_excepction.to_string(), expected_error_string); + } } From 9845fc5232e7bba24017963b1f9dce0c30e37cf5 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 18:32:23 -0300 Subject: [PATCH 36/52] Remove debug format from erros containing MaybeRelocatable and Relocatable --- src/types/relocatable.rs | 10 +++++++--- src/vm/errors/vm_errors.rs | 30 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/types/relocatable.rs b/src/types/relocatable.rs index a444a4a74b..05d905ae35 100644 --- a/src/types/relocatable.rs +++ b/src/types/relocatable.rs @@ -70,14 +70,18 @@ impl From for MaybeRelocatable { impl Display for MaybeRelocatable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - MaybeRelocatable::RelocatableValue(rel) => { - write!(f, "{}:{}", rel.segment_index, rel.offset) - } + MaybeRelocatable::RelocatableValue(rel) => rel.fmt(f), MaybeRelocatable::Int(num) => write!(f, "{}", num), } } } +impl Display for Relocatable { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}", self.segment_index, self.offset) + } +} + impl Add for Relocatable { type Output = Relocatable; fn add(self, other: usize) -> Self { diff --git a/src/vm/errors/vm_errors.rs b/src/vm/errors/vm_errors.rs index da62dfbc62..f89ac0c7ce 100644 --- a/src/vm/errors/vm_errors.rs +++ b/src/vm/errors/vm_errors.rs @@ -30,9 +30,9 @@ pub enum VirtualMachineError { UnconstrainedResAssertEq, #[error("An ASSERT_EQ instruction failed: {0} != {1}.")] DiffAssertValues(MaybeRelocatable, MaybeRelocatable), - #[error("Call failed to write return-pc (inconsistent op0): {0:?} != {1:?}. Did you forget to increment ap?")] + #[error("Call failed to write return-pc (inconsistent op0): {0} != {1}. Did you forget to increment ap?")] CantWriteReturnPc(MaybeRelocatable, MaybeRelocatable), - #[error("Call failed to write return-fp (inconsistent dst): {0:?} != {1:?}. Did you forget to increment ap?")] + #[error("Call failed to write return-fp (inconsistent dst): {0} != {1}. Did you forget to increment ap?")] CantWriteReturnFp(MaybeRelocatable, MaybeRelocatable), #[error("Couldn't get or load dst")] NoDst, @@ -50,11 +50,11 @@ pub enum VirtualMachineError { NotImplemented, #[error("Can only subtract two relocatable values of the same segment")] DiffIndexSub, - #[error("Inconsistent auto-deduction for builtin {0}, expected {1:?}, got {2:?}")] + #[error("Inconsistent auto-deduction for builtin {0}, expected {1}, got {2:?}")] InconsistentAutoDeduction(String, MaybeRelocatable, Option), #[error(transparent)] RunnerError(#[from] RunnerError), - #[error("Invalid hint encoding at pc: {0:?}")] + #[error("Invalid hint encoding at pc: {0}")] InvalidHintEncoding(MaybeRelocatable), #[error(transparent)] MemoryError(#[from] MemoryError), @@ -62,11 +62,11 @@ pub enum VirtualMachineError { NoRangeCheckBuiltin, #[error("Expected ecdsa builtin to be present")] NoSignatureBuiltin, - #[error("Failed to retrieve value from address {0:?}")] + #[error("Failed to retrieve value from address {0}")] MemoryGet(MaybeRelocatable), - #[error("Expected integer at address {0:?}")] + #[error("Expected integer at address {0}")] ExpectedInteger(MaybeRelocatable), - #[error("Expected relocatable at address {0:?}")] + #[error("Expected relocatable at address {0}")] ExpectedRelocatable(MaybeRelocatable), #[error("Failed to get ids for hint execution")] FailedToGetIds, @@ -74,7 +74,7 @@ pub enum VirtualMachineError { NonLeFelt(BigInt, BigInt), #[error("Div out of range: 0 < {0} <= {1}")] OutOfValidRange(BigInt, BigInt), - #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0:?} is out of range")] + #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")] ValueOutOfRange(BigInt), #[error("Value: {0} should be positive")] ValueNotPositive(BigInt), @@ -86,11 +86,11 @@ pub enum VirtualMachineError { SplitIntNotZero, #[error("split_int(): Limb {0} is out of range.")] SplitIntLimbOutOfRange(BigInt), - #[error("Failed to compare {0:?} and {1:?}, cant compare a relocatable to an integer value")] + #[error("Failed to compare {0} and {1}, cant compare a relocatable to an integer value")] DiffTypeComparison(MaybeRelocatable, MaybeRelocatable), - #[error("assert_not_equal failed: {0:?} = {1:?}")] + #[error("assert_not_equal failed: {0} = {1}")] AssertNotEqualFail(MaybeRelocatable, MaybeRelocatable), - #[error("Failed to compare {0:?} and {1:?}, cant compare two relocatable values of different segment indexes")] + #[error("Failed to compare {0} and {1}, cant compare two relocatable values of different segment indexes")] DiffIndexComp(Relocatable, Relocatable), #[error("Value: {0} is outside of the range [0, 2**250)")] ValueOutside250BitRange(BigInt), @@ -132,7 +132,7 @@ pub enum VirtualMachineError { NoneApTrackingData, #[error("Tracking groups should be the same, got {0} and {1}")] InvalidTrackingGroup(usize, usize), - #[error("Expected relocatable for ap, got {0:?}")] + #[error("Expected relocatable for ap, got {0}")] InvalidApValue(MaybeRelocatable), #[error("Dict Error: Tried to create a dict whithout an initial dict")] NoInitialDict, @@ -178,13 +178,13 @@ pub enum VirtualMachineError { CouldntPopPositions, #[error("unexpected verify multiplicity fail: last_pos not found")] LastPosNotFound, - #[error("Set's starting point {0:?} is bigger it's ending point {1:?}")] + #[error("Set's starting point {0} is bigger it's ending point {1}")] InvalidSetRange(MaybeRelocatable, MaybeRelocatable), #[error("Failed to construct a fixed size array of size: {0}")] FixedSizeArrayFail(usize), #[error("{0}")] AssertionFailed(String), - #[error("Wrong dict pointer supplied. Got {0:?}, expected {1:?}.")] + #[error("Wrong dict pointer supplied. Got {0}, expected {1}.")] MismatchedDictPtr(Relocatable, Relocatable), #[error("Integer must be postive or zero, got: {0}")] SecpSplitNegative(BigInt), @@ -218,7 +218,7 @@ pub enum VirtualMachineError { NoImm, #[error("Tried to compute an address but there was no register in the reference.")] NoRegisterInReference, - #[error("Couldn't compute operand {0} at address {1:?}")] + #[error("Couldn't compute operand {0} at address {1}")] FailedToComputeOperands(String, Relocatable), #[error("Custom Hint Error: {0}")] CustomHint(String), From 8b1e11c92ac9afa1719b6c70264cfd5ca799bfe3 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 18:38:51 -0300 Subject: [PATCH 37/52] Add tests for display implementation --- src/types/relocatable.rs | 24 ++++++++++++++++++++++++ src/vm/vm_core.rs | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/types/relocatable.rs b/src/types/relocatable.rs index 05d905ae35..7725eff7b4 100644 --- a/src/types/relocatable.rs +++ b/src/types/relocatable.rs @@ -868,4 +868,28 @@ mod tests { mayberelocatable!(3).get_relocatable() ) } + + #[test] + fn relocatable_display() { + assert_eq!( + format!("{}", Relocatable::from((1, 0))), + String::from("1:0") + ) + } + + #[test] + fn maybe_relocatable_relocatable_display() { + assert_eq!( + format!("{}", MaybeRelocatable::from((1, 0))), + String::from("1:0") + ) + } + + #[test] + fn maybe_relocatable_int_display() { + assert_eq!( + format!("{}", MaybeRelocatable::from(bigint!(6))), + String::from("6") + ) + } } diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 2b073c9191..7b08a5e6ac 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -3313,7 +3313,7 @@ mod tests { ))) )) ); - assert_eq!(error.unwrap_err().to_string(), "Inconsistent auto-deduction for builtin ec_op, expected Int(2739017437753868763038285897969098325279422804143820990343394856167768859289), got Some(Int(2778063437308421278851140253538604815869848682781135193774472480292420096757))"); + assert_eq!(error.unwrap_err().to_string(), "Inconsistent auto-deduction for builtin ec_op, expected 2739017437753868763038285897969098325279422804143820990343394856167768859289, got Some(Int(2778063437308421278851140253538604815869848682781135193774472480292420096757))"); } #[test] From f46e49a73670c77e91a38f8ffda0acefebe8a278 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 18:55:34 -0300 Subject: [PATCH 38/52] Update Changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e17edf5742..81ef45c475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,8 @@ * `pub fn get_location(pc: &usize, runner: &CairoRunner) -> Option` is now `pub fn get_location(pc: usize, runner: &CairoRunner) -> Option` * `pub fn decode_instruction(encoded_instr: i64, mut imm: Option) -> Result` is now `pub fn decode_instruction(encoded_instr: i64, mut imm: Option<&BigInt>) -> Result` * `VmExcepion` field's string format now mirror their cairo-lang conterparts. + +* Add input file contents to traceback [#666](https://github.com/lambdaclass/cairo-rs/pull/666/files) + * Public Api changes: + * `VirtualMachineError` enum variants containing `MaybeRelocatable` and/or `Relocatable` values now use the `Display` format instead of `Debug` in their `Display` implementation + * `get_traceback` now adds the source code line to each traceback entry From e9ecfe42734c0e2640135c87e87a55db78519b92 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 28 Dec 2022 19:16:52 -0300 Subject: [PATCH 39/52] Clippy --- src/vm/errors/vm_exception.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index dad7fc5893..5ba68580e6 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -109,7 +109,7 @@ impl Display for VmException { error_msg.push_str(&format!("{}\n", message)); } if let Some(ref string) = self.traceback { - error_msg.push_str(&format!("{}", string)); + error_msg.push_str(string); } // Write error message write!(f, "{}", error_msg) From 40d06cb2b05c7e2fc00e0cfab157779a097d8d02 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 10:08:55 -0300 Subject: [PATCH 40/52] Remove unnecessary & --- src/vm/errors/vm_exception.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 5ba68580e6..a043b2e850 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -95,7 +95,7 @@ impl Display for VmException { location_msg = format!( "{}\n{}", location.to_string_with_content(message), - &location_msg + location_msg ); // Add parent location info if let Some(parent) = &location.parent_location { From c7b5cfe320b3c0b9dff59209e1074e95a8dccba5 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 10:26:41 -0300 Subject: [PATCH 41/52] Add hint location to InstructionLocation --- src/serde/deserialize_program.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/serde/deserialize_program.rs b/src/serde/deserialize_program.rs index 2cdb29e6ab..becdbc7c45 100644 --- a/src/serde/deserialize_program.rs +++ b/src/serde/deserialize_program.rs @@ -103,6 +103,7 @@ pub struct DebugInfo { #[derive(Deserialize, Debug, PartialEq)] pub struct InstructionLocation { inst: Location, + hints: Vec, } #[derive(Deserialize, Clone, Debug, PartialEq, Eq)] @@ -110,6 +111,12 @@ pub struct InputFile { pub filename: String, } +#[derive(Deserialize, Debug, PartialEq)] +pub struct HintLocation { + location: Location, + n_prefix_newlines: u32, +} + fn bigint_from_number<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, @@ -1147,6 +1154,7 @@ mod tests { start_line: 7, start_col: 5, }, + hints: vec![], }, ), ( @@ -1160,6 +1168,7 @@ mod tests { start_line: 5, start_col: 5, }, + hints: vec![], }, ), ]), @@ -1260,6 +1269,7 @@ mod tests { start_col: 18, }), String::from( "While expanding the reference 'syscall_ptr' in:")) ), start_line: 9, start_col: 18 }, + hints: vec![], }), ] ) }; From 160fe325606bb782050d62231bb3372431880b84 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 10:42:00 -0300 Subject: [PATCH 42/52] Use InstructionLocation instead of Location in insruction_locations field of Program --- src/serde/deserialize_program.rs | 22 +++++++++------------- src/types/program.rs | 6 +++--- src/vm/errors/vm_exception.rs | 29 ++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/serde/deserialize_program.rs b/src/serde/deserialize_program.rs index becdbc7c45..dea2f9351c 100644 --- a/src/serde/deserialize_program.rs +++ b/src/serde/deserialize_program.rs @@ -100,10 +100,10 @@ pub struct DebugInfo { instruction_locations: HashMap, } -#[derive(Deserialize, Debug, PartialEq)] +#[derive(Deserialize, Debug, PartialEq, Eq, Clone)] pub struct InstructionLocation { - inst: Location, - hints: Vec, + pub inst: Location, + pub hints: Vec, } #[derive(Deserialize, Clone, Debug, PartialEq, Eq)] @@ -111,10 +111,10 @@ pub struct InputFile { pub filename: String, } -#[derive(Deserialize, Debug, PartialEq)] +#[derive(Deserialize, Debug, PartialEq, Eq, Clone)] pub struct HintLocation { - location: Location, - n_prefix_newlines: u32, + pub location: Location, + pub n_prefix_newlines: u32, } fn bigint_from_number<'de, D>(deserializer: D) -> Result, D::Error> @@ -368,13 +368,9 @@ pub fn deserialize_program( .into_iter() .filter(|attr| attr.name == "error_message") .collect(), - instruction_locations: program_json.debug_info.map(|debug_info| { - debug_info - .instruction_locations - .into_iter() - .map(|(offset, instruction_location)| (offset, instruction_location.inst)) - .collect() - }), + instruction_locations: program_json + .debug_info + .map(|debug_info| debug_info.instruction_locations), }) } diff --git a/src/types/program.rs b/src/types/program.rs index a349daacb7..5e94ebd84f 100644 --- a/src/types/program.rs +++ b/src/types/program.rs @@ -1,5 +1,5 @@ use crate::serde::deserialize_program::{ - deserialize_program, Attribute, HintParams, Identifier, Location, ReferenceManager, + deserialize_program, Attribute, HintParams, Identifier, InstructionLocation, ReferenceManager, }; use crate::types::errors::program_errors::ProgramError; use crate::types::relocatable::MaybeRelocatable; @@ -22,7 +22,7 @@ pub struct Program { pub reference_manager: ReferenceManager, pub identifiers: HashMap, pub error_message_attributes: Vec, - pub instruction_locations: Option>, + pub instruction_locations: Option>, } impl Program { @@ -36,7 +36,7 @@ impl Program { reference_manager: ReferenceManager, identifiers: HashMap, error_message_attributes: Vec, - instruction_locations: Option>, + instruction_locations: Option>, ) -> Result { Ok(Self { builtins, diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index a043b2e850..328a741aef 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -56,7 +56,7 @@ pub fn get_location(pc: usize, runner: &CairoRunner) -> Option { .instruction_locations .as_ref()? .get(&pc) - .cloned() + .map(|inst_location| inst_location.inst.clone()) } // Returns the traceback at the current pc. @@ -169,7 +169,7 @@ mod test { use std::path::Path; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; - use crate::serde::deserialize_program::{Attribute, InputFile}; + use crate::serde::deserialize_program::{Attribute, InputFile, InstructionLocation}; use crate::types::program::Program; use crate::types::relocatable::Relocatable; use crate::utils::test_utils::*; @@ -188,8 +188,13 @@ mod test { start_line: 1, start_col: 1, }; - let program = - program!(instruction_locations = Some(HashMap::from([(pc, location.clone())])),); + let instruction_location = InstructionLocation { + inst: location, + hints: vec![], + }; + let program = program!( + instruction_locations = Some(HashMap::from([(pc, instruction_location.clone())])), + ); let runner = cairo_runner!(program); let vm_excep = VmException { pc, @@ -408,8 +413,13 @@ mod test { start_line: 1, start_col: 1, }; - let program = - program!(instruction_locations = Some(HashMap::from([(2, location.clone())])),); + let instruction_location = InstructionLocation { + inst: location.clone(), + hints: vec![], + }; + let program = program!( + instruction_locations = Some(HashMap::from([(2, instruction_location.clone())])), + ); let runner = cairo_runner!(program); assert_eq!(get_location(2, &runner), Some(location)); } @@ -426,7 +436,12 @@ mod test { start_line: 1, start_col: 1, }; - let program = program!(instruction_locations = Some(HashMap::from([(2, location)])),); + let instruction_location = InstructionLocation { + inst: location, + hints: vec![], + }; + let program = + program!(instruction_locations = Some(HashMap::from([(2, instruction_location)])),); let runner = cairo_runner!(program); assert_eq!(get_location(3, &runner), None); } From bd6111adb991dfc029c0844b4a7597abd077c784 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 11:35:29 -0300 Subject: [PATCH 43/52] Add hint location logic to get_location --- src/vm/errors/vm_exception.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 328a741aef..65bacff78b 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -32,7 +32,7 @@ impl VmException { let error_attr_value = get_error_attr_value(pc, runner); VmException { pc, - inst_location: get_location(pc, runner), + inst_location: get_location(pc, runner, None), inner_exc: error, error_attr_value, traceback: get_traceback(vm, runner), @@ -50,13 +50,20 @@ pub fn get_error_attr_value(pc: usize, runner: &CairoRunner) -> Option { (!errors.is_empty()).then(|| errors) } -pub fn get_location(pc: usize, runner: &CairoRunner) -> Option { - runner - .program - .instruction_locations - .as_ref()? - .get(&pc) - .map(|inst_location| inst_location.inst.clone()) +pub fn get_location( + pc: usize, + runner: &CairoRunner, + hint_index: Option, +) -> Option { + let instruction_location = runner.program.instruction_locations.as_ref()?.get(&pc)?; + if let Some(index) = hint_index { + instruction_location + .hints + .get(index) + .map(|hint_location| hint_location.location.clone()) + } else { + Some(instruction_location.inst.clone()) + } } // Returns the traceback at the current pc. @@ -66,7 +73,7 @@ pub fn get_traceback(vm: &VirtualMachine, runner: &CairoRunner) -> Option traceback.push_str(&format!( "{}\n", location.to_string_with_content(&format!("(pc=0:{})", traceback_pc.offset)) @@ -189,7 +196,7 @@ mod test { start_col: 1, }; let instruction_location = InstructionLocation { - inst: location, + inst: location.clone(), hints: vec![], }; let program = program!( @@ -421,7 +428,7 @@ mod test { instruction_locations = Some(HashMap::from([(2, instruction_location.clone())])), ); let runner = cairo_runner!(program); - assert_eq!(get_location(2, &runner), Some(location)); + assert_eq!(get_location(2, &runner, None), Some(location)); } #[test] @@ -443,7 +450,7 @@ mod test { let program = program!(instruction_locations = Some(HashMap::from([(2, instruction_location)])),); let runner = cairo_runner!(program); - assert_eq!(get_location(3, &runner), None); + assert_eq!(get_location(3, &runner, None), None); } #[test] From a9045fa2f1e44b613232846978a5cc50c5922a51 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 11:39:32 -0300 Subject: [PATCH 44/52] Add rought version of VirtualMachineError::Hint --- src/vm/errors/vm_errors.rs | 2 ++ src/vm/vm_core.rs | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vm/errors/vm_errors.rs b/src/vm/errors/vm_errors.rs index f89ac0c7ce..4a82e38392 100644 --- a/src/vm/errors/vm_errors.rs +++ b/src/vm/errors/vm_errors.rs @@ -240,4 +240,6 @@ pub enum VirtualMachineError { InvalidArgCount(usize, usize), #[error("{0}, {1}")] ErrorMessageAttribute(String, Box), + #[error("{1}")] + Hint(usize, Box), } diff --git a/src/vm/vm_core.rs b/src/vm/vm_core.rs index 7b08a5e6ac..05333969d0 100644 --- a/src/vm/vm_core.rs +++ b/src/vm/vm_core.rs @@ -525,8 +525,10 @@ impl VirtualMachine { constants: &HashMap, ) -> Result<(), VirtualMachineError> { if let Some(hint_list) = hint_data_dictionary.get(&self.run_context.pc.offset) { - for hint_data in hint_list.iter() { - hint_executor.execute_hint(self, exec_scopes, hint_data, constants)? + for (hint_index, hint_data) in hint_list.iter().enumerate() { + hint_executor + .execute_hint(self, exec_scopes, hint_data, constants) + .map_err(|err| VirtualMachineError::Hint(hint_index, Box::new(err)))? } } Ok(()) From 085d6eb86780a3984cdfb3d40911939fae8a85a2 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 11:51:07 -0300 Subject: [PATCH 45/52] Add test for error display on HintError --- src/vm/errors/vm_errors.rs | 2 +- src/vm/errors/vm_exception.rs | 42 ++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/vm/errors/vm_errors.rs b/src/vm/errors/vm_errors.rs index 4a82e38392..917197a731 100644 --- a/src/vm/errors/vm_errors.rs +++ b/src/vm/errors/vm_errors.rs @@ -240,6 +240,6 @@ pub enum VirtualMachineError { InvalidArgCount(usize, usize), #[error("{0}, {1}")] ErrorMessageAttribute(String, Box), - #[error("{1}")] + #[error("Got an exception while executing a hint: {1}")] Hint(usize, Box), } diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 65bacff78b..1a8f4522f4 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -30,9 +30,14 @@ impl VmException { ) -> Self { let pc = vm.run_context.pc.offset; let error_attr_value = get_error_attr_value(pc, runner); + let hint_index = if let VirtualMachineError::Hint(hint_index, _) = error { + Some(hint_index) + } else { + None + }; VmException { pc, - inst_location: get_location(pc, runner, None), + inst_location: get_location(pc, runner, hint_index), inner_exc: error, error_attr_value, traceback: get_traceback(vm, runner), @@ -627,4 +632,39 @@ cairo_programs/bad_programs/bad_range_check.cairo:11:5: (pc=0:6) let vm_excepction = VmException::from_vm_error(&cairo_runner, &vm, error); assert_eq!(vm_excepction.to_string(), expected_error_string); } + + #[test] + fn run_bad_usort_and_check_error_displayed() { + let expected_error_string = r#"cairo_programs/bad_programs/bad_usort.cairo:79:5: Error at pc=0:75: +Got an exception while executing a hint: unexpected verify multiplicity fail: positions length != 0 + %{ assert len(positions) == 0 %} + ^******************************^ +Cairo traceback (most recent call last): +cairo_programs/bad_programs/bad_usort.cairo:91:48: (pc=0:97) + let (output_len, output, multiplicities) = usort(input_len=3, input=input_array); + ^***********************************^ +cairo_programs/bad_programs/bad_usort.cairo:36:5: (pc=0:30) + verify_usort{output=output}( + ^**************************^ +cairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60) + verify_multiplicity(multiplicity=multiplicity, input_len=input_len, input=input, value=value); + ^*******************************************************************************************^ +"#; + let program = Program::from_file( + Path::new("cairo_programs/bad_programs/bad_usort.json"), + Some("main"), + ) + .expect("Call to `Program::from_file()` failed."); + + let mut hint_processor = BuiltinHintProcessor::new_empty(); + let mut cairo_runner = cairo_runner!(program, "all", false); + let mut vm = vm!(); + + let end = cairo_runner.initialize(&mut vm).unwrap(); + let error = cairo_runner + .run_until_pc(end, &mut vm, &mut hint_processor) + .unwrap_err(); + let vm_excepction = VmException::from_vm_error(&cairo_runner, &vm, error); + assert_eq!(vm_excepction.to_string(), expected_error_string); + } } From 2909f1bd1552af376a3fc33f7a54cebdb82770aa Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 11:56:19 -0300 Subject: [PATCH 46/52] Add test for get_location with hint_index --- src/vm/errors/vm_exception.rs | 41 ++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index 1a8f4522f4..ff6fac7f21 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -181,7 +181,9 @@ mod test { use std::path::Path; use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; - use crate::serde::deserialize_program::{Attribute, InputFile, InstructionLocation}; + use crate::serde::deserialize_program::{ + Attribute, HintLocation, InputFile, InstructionLocation, + }; use crate::types::program::Program; use crate::types::relocatable::Relocatable; use crate::utils::test_utils::*; @@ -458,6 +460,43 @@ mod test { assert_eq!(get_location(3, &runner, None), None); } + #[test] + fn get_location_some_hint_index() { + let location_a = Location { + end_line: 2, + end_col: 2, + input_file: InputFile { + filename: String::from("Folder/file_a.cairo"), + }, + parent_location: None, + start_line: 1, + start_col: 1, + }; + let location_b = Location { + end_line: 3, + end_col: 2, + input_file: InputFile { + filename: String::from("Folder/file_b.cairo"), + }, + parent_location: None, + start_line: 1, + start_col: 5, + }; + let hint_location = HintLocation { + location: location_b.clone(), + n_prefix_newlines: 2, + }; + let instruction_location = InstructionLocation { + inst: location_a, + hints: vec![hint_location], + }; + let program = program!( + instruction_locations = Some(HashMap::from([(2, instruction_location.clone())])), + ); + let runner = cairo_runner!(program); + assert_eq!(get_location(2, &runner, Some(0)), Some(location_b)); + } + #[test] fn get_traceback_bad_dict_update() { let program = Program::from_file( From 5542e3f0cb80e60bb156720852d07175343c7e01 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 14:29:39 -0300 Subject: [PATCH 47/52] Start refactor --- .../builtin_hint_processor_definition.rs | 5 +- .../builtin_hint_processor/usort.rs | 31 ++-- .../hint_processor_definition.rs | 6 +- src/hint_processor/hint_processor_utils.rs | 46 +++--- src/main.rs | 5 +- src/types/exec_scope.rs | 74 ++++----- src/u.cairo | 23 +++ src/vm/errors/hint_errors.rs | 120 +++++++++++++++ src/vm/errors/mod.rs | 1 + src/vm/errors/vm_errors.rs | 143 +++--------------- src/vm/errors/vm_exception.rs | 4 +- 11 files changed, 245 insertions(+), 213 deletions(-) create mode 100644 src/u.cairo create mode 100644 src/vm/errors/hint_errors.rs diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 2bff9d94e5..5fc572306f 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -34,6 +34,7 @@ use crate::hint_processor::builtin_hint_processor::uint256_utils::{ use crate::hint_processor::hint_processor_definition::{HintProcessor, HintReference}; use crate::serde::deserialize_program::ApTracking; use crate::types::exec_scope::ExecutionScopes; +use crate::vm::errors::hint_errors::HintError; use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; @@ -121,10 +122,10 @@ impl HintProcessor for BuiltinHintProcessor { exec_scopes: &mut ExecutionScopes, hint_data: &Box, constants: &HashMap, - ) -> Result<(), VirtualMachineError> { + ) -> Result<(), HintError> { let hint_data = hint_data .downcast_ref::() - .ok_or(VirtualMachineError::WrongHintData)?; + .ok_or(HintError::WrongHintData)?; if let Some(hint_func) = self.extra_hints.get(&hint_data.code) { return hint_func.0( diff --git a/src/hint_processor/builtin_hint_processor/usort.rs b/src/hint_processor/builtin_hint_processor/usort.rs index 8e86742121..fc1b0e7020 100644 --- a/src/hint_processor/builtin_hint_processor/usort.rs +++ b/src/hint_processor/builtin_hint_processor/usort.rs @@ -8,14 +8,14 @@ use crate::{ }, serde::deserialize_program::ApTracking, types::exec_scope::ExecutionScopes, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; use num_bigint::BigInt; use num_traits::ToPrimitive; use std::{any::Any, collections::HashMap}; -pub fn usort_enter_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), VirtualMachineError> { +pub fn usort_enter_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { if let Ok(usort_max_size) = exec_scopes.get::("usort_max_size") { let boxed_max_size: Box = Box::new(usort_max_size); exec_scopes.enter_scope(HashMap::from([( @@ -33,17 +33,15 @@ pub fn usort_body( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let input_ptr = get_ptr_from_var_name("input", vm, ids_data, ap_tracking)?; let usort_max_size = exec_scopes.get::("usort_max_size"); let input_len = get_integer_from_var_name("input_len", vm, ids_data, ap_tracking)?; - let input_len_u64 = input_len - .to_u64() - .ok_or(VirtualMachineError::BigintToUsizeFail)?; + let input_len_u64 = input_len.to_u64().ok_or(HintError::BigintToUsizeFail)?; if let Ok(usort_max_size) = usort_max_size { if input_len_u64 > usort_max_size { - return Err(VirtualMachineError::UsortOutOfRange( + return Err(HintError::UsortOutOfRange( usort_max_size, input_len.into_owned(), )); @@ -84,7 +82,8 @@ pub fn usort_body( vm, ids_data, ap_tracking, - ) + )?; + Ok(()) } pub fn verify_usort( @@ -92,26 +91,24 @@ pub fn verify_usort( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?.clone(); let mut positions = exec_scopes .get_mut_dict_ref::>("positions_dict")? .remove(&value) - .ok_or(VirtualMachineError::UnexpectedPositionsDictFail)?; + .ok_or(HintError::UnexpectedPositionsDictFail)?; positions.reverse(); exec_scopes.insert_value("positions", positions); exec_scopes.insert_value("last_pos", bigint!(0)); Ok(()) } -pub fn verify_multiplicity_assert( - exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +pub fn verify_multiplicity_assert(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { let positions_len = exec_scopes.get_list_ref::("positions")?.len(); if positions_len == 0 { Ok(()) } else { - Err(VirtualMachineError::PositionsLengthNotZero) + Err(HintError::PositionsLengthNotZero) } } @@ -120,11 +117,11 @@ pub fn verify_multiplicity_body( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let current_pos = exec_scopes .get_mut_list_ref::("positions")? .pop() - .ok_or(VirtualMachineError::CouldntPopPositions)?; + .ok_or(HintError::CouldntPopPositions)?; let pos_diff = bigint!(current_pos) - exec_scopes.get::("last_pos")?; insert_value_from_var_name("next_item_index", pos_diff, vm, ids_data, ap_tracking)?; exec_scopes.insert_value("last_pos", bigint!(current_pos + 1)); @@ -169,7 +166,7 @@ mod tests { let mut exec_scopes = scope![("usort_max_size", 1_u64)]; assert_eq!( run_hint!(vm, ids_data, USORT_BODY, &mut exec_scopes), - Err(VirtualMachineError::UsortOutOfRange(1, bigint!(5))) + Err(HintError::UsortOutOfRange(1, bigint!(5))) ); } } diff --git a/src/hint_processor/hint_processor_definition.rs b/src/hint_processor/hint_processor_definition.rs index bb4536038f..0c5a921784 100644 --- a/src/hint_processor/hint_processor_definition.rs +++ b/src/hint_processor/hint_processor_definition.rs @@ -2,7 +2,7 @@ use crate::serde::deserialize_program::ApTracking; use crate::serde::deserialize_program::OffsetValue; use crate::types::exec_scope::ExecutionScopes; use crate::types::instruction::Register; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use std::any::Any; @@ -22,7 +22,7 @@ pub trait HintProcessor { hint_data: &Box, //Constant values extracted from the program specification. constants: &HashMap, - ) -> Result<(), VirtualMachineError>; + ) -> Result<(), HintError>; //Transforms hint data outputed by the VM into whichever format will be later used by execute_hint fn compile_hint( @@ -36,7 +36,7 @@ pub trait HintProcessor { reference_ids: &HashMap, //List of all references (key corresponds to element of the previous dictionary) references: &HashMap, - ) -> Result, VirtualMachineError>; + ) -> Result, HintError>; } #[derive(Debug, PartialEq, Clone)] diff --git a/src/hint_processor/hint_processor_utils.rs b/src/hint_processor/hint_processor_utils.rs index aa611f52d6..84629cf0b9 100644 --- a/src/hint_processor/hint_processor_utils.rs +++ b/src/hint_processor/hint_processor_utils.rs @@ -9,7 +9,10 @@ use crate::{ instruction::Register, relocatable::{MaybeRelocatable, Relocatable}, }, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{ + errors::{hint_errors::HintError, vm_errors::VirtualMachineError}, + vm_core::VirtualMachine, + }, }; use super::hint_processor_definition::HintReference; @@ -20,9 +23,10 @@ pub fn insert_value_from_reference( vm: &mut VirtualMachine, hint_reference: &HintReference, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let var_addr = compute_addr_from_reference(hint_reference, vm, ap_tracking)?; vm.insert_value(&var_addr, value) + .map_err(HintError::InternalError) } ///Returns the Integer value stored in the given ids variable @@ -30,7 +34,7 @@ pub fn get_integer_from_reference<'a>( vm: &'a VirtualMachine, hint_reference: &'a HintReference, ap_tracking: &ApTracking, -) -> Result, VirtualMachineError> { +) -> Result, HintError> { // if the reference register is none, this means it is an immediate value and we // should return that value. @@ -39,7 +43,7 @@ pub fn get_integer_from_reference<'a>( } let var_addr = compute_addr_from_reference(hint_reference, vm, ap_tracking)?; - vm.get_integer(&var_addr) + vm.get_integer(&var_addr).map_err(HintError::InternalError) } ///Returns the Relocatable value stored in the given ids variable @@ -47,7 +51,7 @@ pub fn get_ptr_from_reference( vm: &VirtualMachine, hint_reference: &HintReference, ap_tracking: &ApTracking, -) -> Result { +) -> Result { let var_addr = compute_addr_from_reference(hint_reference, vm, ap_tracking)?; if hint_reference.dereference { Ok(vm.get_relocatable(&var_addr)?) @@ -63,7 +67,7 @@ pub fn compute_addr_from_reference( vm: &VirtualMachine, //ApTracking of the Hint itself hint_ap_tracking: &ApTracking, -) -> Result { +) -> Result { let offset1 = if let OffsetValue::Reference(_register, _offset, _deref) = &hint_reference.offset1 { get_offset_value_reference( @@ -74,7 +78,7 @@ pub fn compute_addr_from_reference( )? .get_relocatable()? } else { - return Err(VirtualMachineError::NoRegisterInReference); + return Err(HintError::NoRegisterInReference); }; match &hint_reference.offset2 { @@ -91,7 +95,7 @@ pub fn compute_addr_from_reference( Ok(offset1 + bigint_to_usize(value.get_int_ref()?)?) } OffsetValue::Value(value) => Ok(offset1 + *value), - _ => Err(VirtualMachineError::NoRegisterInReference), + _ => Err(HintError::NoRegisterInReference), } } @@ -99,16 +103,16 @@ fn apply_ap_tracking_correction( ap: &Relocatable, ref_ap_tracking: &ApTracking, hint_ap_tracking: &ApTracking, -) -> Result { +) -> Result { // check that both groups are the same if ref_ap_tracking.group != hint_ap_tracking.group { - return Err(VirtualMachineError::InvalidTrackingGroup( + return Err(HintError::InvalidTrackingGroup( ref_ap_tracking.group, hint_ap_tracking.group, )); } let ap_diff = hint_ap_tracking.offset - ref_ap_tracking.offset; - ap.sub(ap_diff) + ap.sub(ap_diff).map_err(HintError::InternalError) } //Tries to convert a BigInt value to usize @@ -128,15 +132,15 @@ fn get_offset_value_reference( hint_reference: &HintReference, hint_ap_tracking: &ApTracking, offset_value: &OffsetValue, -) -> Result { +) -> Result { // let (register, offset , deref) = if let OffsetValue::Reference(register, offset ,deref ) = offset_value { // (register, offset_value, deref) // } else { - // return Err(VirtualMachineError::FailedToGetIds); + // return Err(HintError::FailedToGetIds); // }; let (register, offset, deref) = match offset_value { OffsetValue::Reference(register, offset, deref) => (register, offset, deref), - _ => return Err(VirtualMachineError::FailedToGetIds), + _ => return Err(HintError::FailedToGetIds), }; let base_addr = if register == &Register::FP { @@ -145,20 +149,20 @@ fn get_offset_value_reference( let var_ap_trackig = hint_reference .ap_tracking_data .as_ref() - .ok_or(VirtualMachineError::NoneApTrackingData)?; + .ok_or(HintError::NoneApTrackingData)?; apply_ap_tracking_correction(&vm.get_ap(), var_ap_trackig, hint_ap_tracking)? }; if offset.is_negative() && base_addr.offset < offset.abs() as usize { - return Err(VirtualMachineError::FailedToGetIds); + return Err(HintError::FailedToGetIds); } if *deref { Ok(vm .get_maybe(&(base_addr + *offset)) - .map_err(|_| VirtualMachineError::FailedToGetIds)? - .ok_or(VirtualMachineError::FailedToGetIds)?) + .map_err(|_| HintError::FailedToGetIds)? + .ok_or(HintError::FailedToGetIds)?) } else { Ok((base_addr + *offset).into()) } @@ -243,7 +247,7 @@ mod tests { assert_eq!( compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()), - Err(VirtualMachineError::NoRegisterInReference) + Err(HintError::NoRegisterInReference) ); } @@ -257,7 +261,7 @@ mod tests { assert_eq!( compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -270,7 +274,7 @@ mod tests { assert_eq!( apply_ap_tracking_correction(&relocatable!(1, 0), &ref_ap_tracking, &hint_ap_tracking), - Err(VirtualMachineError::InvalidTrackingGroup(1, 2)) + Err(HintError::InvalidTrackingGroup(1, 2)) ); } } diff --git a/src/main.rs b/src/main.rs index f8e963fb8f..d8a8a62d16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,7 +57,10 @@ fn main() -> Result<(), CairoRunError> { &mut hint_executor, ) { Ok(runner) => runner, - Err(error) => return Err(error), + Err(error) => { + println!("{}", error); + return Err(error); + } }; if let Some(trace_path) = args.trace_file { diff --git a/src/types/exec_scope.rs b/src/types/exec_scope.rs index 1d9a1c7556..20559ecf6c 100644 --- a/src/types/exec_scope.rs +++ b/src/types/exec_scope.rs @@ -1,7 +1,7 @@ use crate::{ any_box, hint_processor::builtin_hint_processor::dict_manager::DictManager, - vm::errors::{exec_scope_errors::ExecScopeError, vm_errors::VirtualMachineError}, + vm::errors::{exec_scope_errors::ExecScopeError, hint_errors::HintError}, }; use std::{any::Any, cell::RefCell, collections::HashMap, rc::Rc}; @@ -32,21 +32,17 @@ impl ExecutionScopes { ///Returns a mutable reference to the dictionary containing the variables present in the current scope pub fn get_local_variables_mut( &mut self, - ) -> Result<&mut HashMap>, VirtualMachineError> { + ) -> Result<&mut HashMap>, HintError> { self.data .last_mut() - .ok_or(VirtualMachineError::MainScopeError( - ExecScopeError::NoScopeError, - )) + .ok_or(HintError::FromScopeError(ExecScopeError::NoScopeError)) } ///Returns a dictionary containing the variables present in the current scope - pub fn get_local_variables( - &self, - ) -> Result<&HashMap>, VirtualMachineError> { - self.data.last().ok_or(VirtualMachineError::MainScopeError( - ExecScopeError::NoScopeError, - )) + pub fn get_local_variables(&self) -> Result<&HashMap>, HintError> { + self.data + .last() + .ok_or(HintError::FromScopeError(ExecScopeError::NoScopeError)) } ///Removes a variable from the current scope given its name @@ -64,120 +60,110 @@ impl ExecutionScopes { } ///Returns the value in the current execution scope that matches the name and is of the given generic type - pub fn get(&self, name: &str) -> Result { + pub fn get(&self, name: &str) -> Result { let mut val: Option = None; if let Some(variable) = self.get_local_variables()?.get(name) { if let Some(int) = variable.downcast_ref::() { val = Some(int.clone()); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Returns a reference to the value in the current execution scope that matches the name and is of the given generic type - pub fn get_ref(&self, name: &str) -> Result<&T, VirtualMachineError> { + pub fn get_ref(&self, name: &str) -> Result<&T, HintError> { let mut val: Option<&T> = None; if let Some(variable) = self.get_local_variables()?.get(name) { if let Some(int) = variable.downcast_ref::() { val = Some(int); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Returns a mutable reference to the value in the current execution scope that matches the name and is of the given generic type - pub fn get_mut_ref(&mut self, name: &str) -> Result<&mut T, VirtualMachineError> { + pub fn get_mut_ref(&mut self, name: &str) -> Result<&mut T, HintError> { let mut val: Option<&mut T> = None; if let Some(variable) = self.get_local_variables_mut()?.get_mut(name) { if let Some(int) = variable.downcast_mut::() { val = Some(int); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Returns the value in the current execution scope that matches the name - pub fn get_any_boxed_ref(&self, name: &str) -> Result<&Box, VirtualMachineError> { + pub fn get_any_boxed_ref(&self, name: &str) -> Result<&Box, HintError> { if let Some(variable) = self.get_local_variables()?.get(name) { return Ok(variable); } - Err(VirtualMachineError::VariableNotInScopeError( - name.to_string(), - )) + Err(HintError::VariableNotInScopeError(name.to_string())) } ///Returns the value in the current execution scope that matches the name - pub fn get_any_boxed_mut( - &mut self, - name: &str, - ) -> Result<&mut Box, VirtualMachineError> { + pub fn get_any_boxed_mut(&mut self, name: &str) -> Result<&mut Box, HintError> { if let Some(variable) = self.get_local_variables_mut()?.get_mut(name) { return Ok(variable); } - Err(VirtualMachineError::VariableNotInScopeError( - name.to_string(), - )) + Err(HintError::VariableNotInScopeError(name.to_string())) } ///Returns the value in the current execution scope that matches the name and is of type List - pub fn get_list(&self, name: &str) -> Result, VirtualMachineError> { + pub fn get_list(&self, name: &str) -> Result, HintError> { let mut val: Option> = None; if let Some(variable) = self.get_local_variables()?.get(name) { if let Some(list) = variable.downcast_ref::>() { val = Some(list.clone()); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Returns a reference to the value in the current execution scope that matches the name and is of type List - pub fn get_list_ref(&self, name: &str) -> Result<&Vec, VirtualMachineError> { + pub fn get_list_ref(&self, name: &str) -> Result<&Vec, HintError> { let mut val: Option<&Vec> = None; if let Some(variable) = self.get_local_variables()?.get(name) { if let Some(list) = variable.downcast_ref::>() { val = Some(list); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Returns a mutable reference to the value in the current execution scope that matches the name and is of type List - pub fn get_mut_list_ref( - &mut self, - name: &str, - ) -> Result<&mut Vec, VirtualMachineError> { + pub fn get_mut_list_ref(&mut self, name: &str) -> Result<&mut Vec, HintError> { let mut val: Option<&mut Vec> = None; if let Some(variable) = self.get_local_variables_mut()?.get_mut(name) { if let Some(list) = variable.downcast_mut::>() { val = Some(list); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Returns the value in the dict manager - pub fn get_dict_manager(&self) -> Result>, VirtualMachineError> { + pub fn get_dict_manager(&self) -> Result>, HintError> { let mut val: Option>> = None; if let Some(variable) = self.get_local_variables()?.get("dict_manager") { if let Some(dict_manager) = variable.downcast_ref::>>() { val = Some(dict_manager.clone()); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError("dict_manager".to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError("dict_manager".to_string())) } ///Returns a mutable reference to the value in the current execution scope that matches the name and is of the given type pub fn get_mut_dict_ref( &mut self, name: &str, - ) -> Result<&mut HashMap, VirtualMachineError> { + ) -> Result<&mut HashMap, HintError> { let mut val: Option<&mut HashMap> = None; if let Some(variable) = self.get_local_variables_mut()?.get_mut(name) { if let Some(dict) = variable.downcast_mut::>() { val = Some(dict); } } - val.ok_or_else(|| VirtualMachineError::VariableNotInScopeError(name.to_string())) + val.ok_or_else(|| HintError::VariableNotInScopeError(name.to_string())) } ///Inserts the boxed value into the current scope @@ -394,7 +380,7 @@ mod tests { assert_eq!( scopes.get_list::("no_variable"), - Err(VirtualMachineError::VariableNotInScopeError( + Err(HintError::VariableNotInScopeError( "no_variable".to_string() )) ); @@ -413,13 +399,13 @@ mod tests { assert_eq!( scopes.get_mut_ref::("no_variable"), - Err(VirtualMachineError::VariableNotInScopeError( + Err(HintError::VariableNotInScopeError( "no_variable".to_string() )) ); assert_eq!( scopes.get_ref::("no_variable"), - Err(VirtualMachineError::VariableNotInScopeError( + Err(HintError::VariableNotInScopeError( "no_variable".to_string() )) ); diff --git a/src/u.cairo b/src/u.cairo new file mode 100644 index 0000000000..e08a84bd9a --- /dev/null +++ b/src/u.cairo @@ -0,0 +1,23 @@ +func assert_not_zero(value: felt){ + %{ + print("test") + a = 1 + 1 + print(a) + %} + if (value == 0) { + value = 1; + } + + return (); +} + +func main() { + assert_not_zero(1); + assert_not_zero(-1); + let x = 500 * 5; + assert_not_zero(x); + tempvar y = -80; + assert_not_zero(y); + + return (); +} \ No newline at end of file diff --git a/src/vm/errors/hint_errors.rs b/src/vm/errors/hint_errors.rs new file mode 100644 index 0000000000..d56abec7b6 --- /dev/null +++ b/src/vm/errors/hint_errors.rs @@ -0,0 +1,120 @@ +use num_bigint::BigInt; +use thiserror::Error; + +use crate::types::relocatable::{MaybeRelocatable, Relocatable}; + +use super::{exec_scope_errors::ExecScopeError, vm_errors::VirtualMachineError}; + +#[derive(Debug, PartialEq, Error)] +pub enum HintError { + #[error("Failed to get ids for hint execution")] + FailedToGetIds, + #[error("Tried to compute an address but there was no register in the reference.")] + NoRegisterInReference, + #[error("Custom Hint Error: {0}")] + CustomHint(String), + #[error("Missing constant: {0}")] + MissingConstant(&'static str), + #[error("Fail to get constants for hint execution")] + FailedToGetConstant, + #[error("Arc too big, {0} must be <= {1} and {2} <= {3}")] + ArcTooBig(BigInt, BigInt, BigInt, BigInt), + #[error("Excluded is supposed to be 2, got {0}")] + ExcludedNot2(BigInt), + #[error("Value: {0} is outside of the range [0, 2**250)")] + ValueOutside250BitRange(BigInt), + #[error("Failed to get scope variables")] + ScopeError, + #[error("Variable {0} not present in current execution scope")] + VariableNotInScopeError(String), + #[error("DictManagerError: Tried to create tracker for a dictionary on segment: {0} when there is already a tracker for a dictionary on this segment")] + CantCreateDictionaryOnTakenSegment(isize), + #[error("Dict Error: No dict tracker found for segment {0}")] + NoDictTracker(isize), + #[error("ict Error: No value found for key: {0}")] + NoValueForKey(BigInt), + #[error("Assertion failed, a = {0} % PRIME is not less than b = {1} % PRIME")] + AssertLtFelt(BigInt, BigInt), + #[error("find_element() can only be used with n_elms <= {0}.\nGot: n_elms = {1}")] + FindElemMaxSize(BigInt, BigInt), + #[error( + "Invalid index found in find_element_index. Index: {0}.\nExpected key: {1}, found_key {2}" + )] + InvalidIndex(BigInt, BigInt, BigInt), + #[error("Found Key is None")] + KeyNotFound, + #[error("AP tracking data is None; could not apply correction to address")] + NoneApTrackingData, + #[error("Tracking groups should be the same, got {0} and {1}")] + InvalidTrackingGroup(usize, usize), + #[error("Expected relocatable for ap, got {0}")] + InvalidApValue(MaybeRelocatable), + #[error("Dict Error: Tried to create a dict whithout an initial dict")] + NoInitialDict, + #[error("squash_dict_inner fail: couldnt find key {0} in accesses_indices")] + NoKeyInAccessIndices(BigInt), + #[error("squash_dict_inner fail: local accessed_indices is empty")] + EmptyAccessIndices, + #[error("squash_dict_inner fail: local current_accessed_indices is empty")] + EmptyCurrentAccessIndices, + #[error("squash_dict_inner fail: local current_accessed_indices not empty, loop ended with remaining unaccounted elements")] + CurrentAccessIndicesNotEmpty, + #[error("Dict Error: Got the wrong value for dict_update, expected value: {0}, got: {1} for key: {2}")] + WrongPrevValue(BigInt, BigInt, BigInt), + #[error("squash_dict_inner fail: Number of used accesses:{0} doesnt match the lengh: {1} of the access_indices at key: {2}")] + NumUsedAccessesAssertFail(BigInt, usize, BigInt), + #[error("squash_dict_inner fail: local keys is not empty")] + KeysNotEmpty, + #[error("squash_dict_inner fail: No keys left but remaining_accesses > 0")] + EmptyKeys, + #[error("squash_dict fail: Accesses array size must be divisible by DictAccess.SIZE")] + PtrDiffNotDivisibleByDictAccessSize, + #[error("squash_dict() can only be used with n_accesses<={0}. ' \nGot: n_accesses={1}")] + SquashDictMaxSizeExceeded(BigInt, BigInt), + #[error("squash_dict fail: n_accesses: {0} is too big to be converted into an iterator")] + NAccessesTooBig(BigInt), + #[error(transparent)] + InternalError(#[from] VirtualMachineError), + #[error("Couldn't convert BigInt to usize")] + BigintToUsizeFail, + #[error("usort() can only be used with input_len<={0}. Got: input_len={1}.")] + UsortOutOfRange(u64, BigInt), + #[error("unexpected usort fail: positions_dict or key value pair not found")] + UnexpectedPositionsDictFail, + #[error("unexpected verify multiplicity fail: positions not found")] + PositionsNotFound, + #[error("unexpected verify multiplicity fail: positions length != 0")] + PositionsLengthNotZero, + #[error("unexpected verify multiplicity fail: couldn't pop positions")] + CouldntPopPositions, + #[error("unexpected verify multiplicity fail: last_pos not found")] + LastPosNotFound, + #[error("Set's starting point {0} is bigger it's ending point {1}")] + InvalidSetRange(MaybeRelocatable, MaybeRelocatable), + #[error("Failed to construct a fixed size array of size: {0}")] + FixedSizeArrayFail(usize), + #[error("{0}")] + AssertionFailed(String), + #[error("Wrong dict pointer supplied. Got {0}, expected {1}.")] + MismatchedDictPtr(Relocatable, Relocatable), + #[error("Integer must be postive or zero, got: {0}")] + SecpSplitNegative(BigInt), + #[error("Integer: {0} out of range")] + SecpSplitutOfRange(BigInt), + #[error("verify_zero: Invalid input {0}")] + SecpVerifyZero(BigInt), + #[error("unsafe_keccak() can only be used with length<={0}. Got: length={1}")] + KeccakMaxSize(BigInt, BigInt), + #[error("Invalid word size: {0}")] + InvalidWordSize(BigInt), + #[error("Invalid input length, Got: length={0}")] + InvalidKeccakInputLength(BigInt), + #[error(transparent)] + FromScopeError(#[from] ExecScopeError), + #[error("assert_not_equal failed: {0} = {1}")] + AssertNotEqualFail(MaybeRelocatable, MaybeRelocatable), + #[error("split_int(): value is out of range")] + SplitIntNotZero, + #[error("split_int(): Limb {0} is out of range.")] + SplitIntLimbOutOfRange(BigInt), +} diff --git a/src/vm/errors/mod.rs b/src/vm/errors/mod.rs index d6b3dbad00..552f9217d5 100644 --- a/src/vm/errors/mod.rs +++ b/src/vm/errors/mod.rs @@ -1,5 +1,6 @@ pub mod cairo_run_errors; pub mod exec_scope_errors; +pub mod hint_errors; pub mod memory_errors; pub mod runner_errors; pub mod trace_errors; diff --git a/src/vm/errors/vm_errors.rs b/src/vm/errors/vm_errors.rs index 917197a731..dc5141d463 100644 --- a/src/vm/errors/vm_errors.rs +++ b/src/vm/errors/vm_errors.rs @@ -1,4 +1,5 @@ use super::exec_scope_errors::ExecScopeError; +use super::hint_errors::HintError; use super::trace_errors::TraceError; use crate::types::relocatable::{MaybeRelocatable, Relocatable}; use crate::vm::errors::memory_errors::MemoryError; @@ -28,6 +29,8 @@ pub enum VirtualMachineError { UnconstrainedResJumpRel, #[error("Res.UNCONSTRAINED cannot be used with Opcode.ASSERT_EQ")] UnconstrainedResAssertEq, + #[error("Couldn't compute operand {0} at address {1}")] + FailedToComputeOperands(String, Relocatable), #[error("An ASSERT_EQ instruction failed: {0} != {1}.")] DiffAssertValues(MaybeRelocatable, MaybeRelocatable), #[error("Call failed to write return-pc (inconsistent op0): {0} != {1}. Did you forget to increment ap?")] @@ -68,8 +71,6 @@ pub enum VirtualMachineError { ExpectedInteger(MaybeRelocatable), #[error("Expected relocatable at address {0}")] ExpectedRelocatable(MaybeRelocatable), - #[error("Failed to get ids for hint execution")] - FailedToGetIds, #[error("Assertion failed, {0}, is not less or equal to {1}")] NonLeFelt(BigInt, BigInt), #[error("Div out of range: 0 < {0} <= {1}")] @@ -82,82 +83,12 @@ pub enum VirtualMachineError { UnknownHint(String), #[error("Value: {0} is outside valid range")] ValueOutsideValidRange(BigInt), - #[error("split_int(): value is out of range")] - SplitIntNotZero, - #[error("split_int(): Limb {0} is out of range.")] - SplitIntLimbOutOfRange(BigInt), #[error("Failed to compare {0} and {1}, cant compare a relocatable to an integer value")] DiffTypeComparison(MaybeRelocatable, MaybeRelocatable), - #[error("assert_not_equal failed: {0} = {1}")] - AssertNotEqualFail(MaybeRelocatable, MaybeRelocatable), - #[error("Failed to compare {0} and {1}, cant compare two relocatable values of different segment indexes")] - DiffIndexComp(Relocatable, Relocatable), - #[error("Value: {0} is outside of the range [0, 2**250)")] - ValueOutside250BitRange(BigInt), - #[error("Can't calculate the square root of negative number: {0})")] - SqrtNegative(BigInt), - #[error("{0} is not divisible by {1}")] - SafeDivFail(BigInt, BigInt), - #[error("{0} is not divisible by {1}")] - SafeDivFailUsize(usize, usize), - #[error("Attempted to divide by zero")] - DividedByZero, - #[error("Failed to calculate the square root of: {0})")] - FailedToGetSqrt(BigInt), #[error("Assertion failed, {0} % {1} is equal to 0")] AssertNotZero(BigInt, BigInt), - #[error(transparent)] - MainScopeError(#[from] ExecScopeError), - #[error("Failed to get scope variables")] - ScopeError, - #[error("Variable {0} not present in current execution scope")] - VariableNotInScopeError(String), - #[error("DictManagerError: Tried to create tracker for a dictionary on segment: {0} when there is already a tracker for a dictionary on this segment")] - CantCreateDictionaryOnTakenSegment(isize), - #[error("Dict Error: No dict tracker found for segment {0}")] - NoDictTracker(isize), - #[error("ict Error: No value found for key: {0}")] - NoValueForKey(BigInt), - #[error("Assertion failed, a = {0} % PRIME is not less than b = {1} % PRIME")] - AssertLtFelt(BigInt, BigInt), - #[error("find_element() can only be used with n_elms <= {0}.\nGot: n_elms = {1}")] - FindElemMaxSize(BigInt, BigInt), - #[error( - "Invalid index found in find_element_index. Index: {0}.\nExpected key: {1}, found_key {2}" - )] - InvalidIndex(BigInt, BigInt, BigInt), - #[error("Found Key is None")] - KeyNotFound, - #[error("AP tracking data is None; could not apply correction to address")] - NoneApTrackingData, - #[error("Tracking groups should be the same, got {0} and {1}")] - InvalidTrackingGroup(usize, usize), - #[error("Expected relocatable for ap, got {0}")] - InvalidApValue(MaybeRelocatable), - #[error("Dict Error: Tried to create a dict whithout an initial dict")] - NoInitialDict, - #[error("squash_dict_inner fail: couldnt find key {0} in accesses_indices")] - NoKeyInAccessIndices(BigInt), - #[error("squash_dict_inner fail: local accessed_indices is empty")] - EmptyAccessIndices, - #[error("squash_dict_inner fail: local current_accessed_indices is empty")] - EmptyCurrentAccessIndices, - #[error("squash_dict_inner fail: local current_accessed_indices not empty, loop ended with remaining unaccounted elements")] - CurrentAccessIndicesNotEmpty, - #[error("Dict Error: Got the wrong value for dict_update, expected value: {0}, got: {1} for key: {2}")] - WrongPrevValue(BigInt, BigInt, BigInt), - #[error("squash_dict_inner fail: Number of used accesses:{0} doesnt match the lengh: {1} of the access_indices at key: {2}")] - NumUsedAccessesAssertFail(BigInt, usize, BigInt), - #[error("squash_dict_inner fail: local keys is not empty")] - KeysNotEmpty, - #[error("squash_dict_inner fail: No keys left but remaining_accesses > 0")] - EmptyKeys, - #[error("squash_dict fail: Accesses array size must be divisible by DictAccess.SIZE")] - PtrDiffNotDivisibleByDictAccessSize, - #[error("squash_dict() can only be used with n_accesses<={0}. ' \nGot: n_accesses={1}")] - SquashDictMaxSizeExceeded(BigInt, BigInt), - #[error("squash_dict fail: n_accesses: {0} is too big to be converted into an iterator")] - NAccessesTooBig(BigInt), + #[error("Failed to compare {0} and {1}, cant compare two relocatable values of different segment indexes")] + DiffIndexComp(Relocatable, Relocatable), #[error("Couldn't convert BigInt to usize")] BigintToUsizeFail, #[error("Couldn't convert BigInt to u64")] @@ -166,42 +97,18 @@ pub enum VirtualMachineError { BigintToU32Fail, #[error("Couldn't convert usize to u32")] UsizeToU32Fail, - #[error("usort() can only be used with input_len<={0}. Got: input_len={1}.")] - UsortOutOfRange(u64, BigInt), - #[error("unexpected usort fail: positions_dict or key value pair not found")] - UnexpectedPositionsDictFail, - #[error("unexpected verify multiplicity fail: positions not found")] - PositionsNotFound, - #[error("unexpected verify multiplicity fail: positions length != 0")] - PositionsLengthNotZero, - #[error("unexpected verify multiplicity fail: couldn't pop positions")] - CouldntPopPositions, - #[error("unexpected verify multiplicity fail: last_pos not found")] - LastPosNotFound, - #[error("Set's starting point {0} is bigger it's ending point {1}")] - InvalidSetRange(MaybeRelocatable, MaybeRelocatable), - #[error("Failed to construct a fixed size array of size: {0}")] - FixedSizeArrayFail(usize), - #[error("{0}")] - AssertionFailed(String), - #[error("Wrong dict pointer supplied. Got {0}, expected {1}.")] - MismatchedDictPtr(Relocatable, Relocatable), - #[error("Integer must be postive or zero, got: {0}")] - SecpSplitNegative(BigInt), - #[error("Integer: {0} out of range")] - SecpSplitutOfRange(BigInt), - #[error("verify_zero: Invalid input {0}")] - SecpVerifyZero(BigInt), - #[error("Cant substract {0} from offset {1}, offsets cant be negative")] - CantSubOffset(usize, usize), - #[error("unsafe_keccak() can only be used with length<={0}. Got: length={1}")] - KeccakMaxSize(BigInt, BigInt), - #[error("Invalid word size: {0}")] - InvalidWordSize(BigInt), - #[error("Invalid input length, Got: length={0}")] - InvalidKeccakInputLength(BigInt), #[error("None value was found in memory range cell")] NoneInMemoryRange, + #[error("Can't calculate the square root of negative number: {0})")] + SqrtNegative(BigInt), + #[error("{0} is not divisible by {1}")] + SafeDivFail(BigInt, BigInt), + #[error("{0} is not divisible by {1}")] + SafeDivFailUsize(usize, usize), + #[error("Attempted to divide by zero")] + DividedByZero, + #[error("Failed to calculate the square root of: {0})")] + FailedToGetSqrt(BigInt), #[error("Expected integer, found: {0:?}")] ExpectedIntAtRange(Option), #[error("Expected size to be in the range from [0, 100), got: {0}")] @@ -216,24 +123,14 @@ pub enum VirtualMachineError { CompileHintFail(String), #[error("op1_addr is Op1Addr.IMM, but no immediate was given")] NoImm, - #[error("Tried to compute an address but there was no register in the reference.")] - NoRegisterInReference, - #[error("Couldn't compute operand {0} at address {1}")] - FailedToComputeOperands(String, Relocatable), - #[error("Custom Hint Error: {0}")] - CustomHint(String), - #[error("Arc too big, {0} must be <= {1} and {2} <= {3}")] - ArcTooBig(BigInt, BigInt, BigInt, BigInt), - #[error("Excluded is supposed to be 2, got {0}")] - ExcludedNot2(BigInt), + #[error("Cant substract {0} from offset {1}, offsets cant be negative")] + CantSubOffset(usize, usize), #[error("Execution reached the end of the program. Requested remaining steps: {0}.")] EndOfProgram(usize), - #[error("Missing constant: {0}")] - MissingConstant(&'static str), - #[error("Fail to get constants for hint execution")] - FailedToGetConstant, #[error(transparent)] TracerError(#[from] TraceError), + #[error(transparent)] + MainScopeError(#[from] ExecScopeError), #[error("Current run is not finished")] RunNotFinished, #[error("Invalid argument count, expected {0} but got {1}")] @@ -241,5 +138,5 @@ pub enum VirtualMachineError { #[error("{0}, {1}")] ErrorMessageAttribute(String, Box), #[error("Got an exception while executing a hint: {1}")] - Hint(usize, Box), + Hint(usize, Box), } diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index ff6fac7f21..2c284ba53d 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -213,12 +213,12 @@ mod test { let vm_excep = VmException { pc, inst_location: Some(location), - inner_exc: VirtualMachineError::CouldntPopPositions, + inner_exc: VirtualMachineError::NoImm, error_attr_value: None, traceback: None, }; assert_eq!( - VmException::from_vm_error(&runner, &vm!(), VirtualMachineError::CouldntPopPositions,), + VmException::from_vm_error(&runner, &vm!(), VirtualMachineError::NoImm,), vm_excep ) } From 4a9e6ddbe9f82c3316834eabcad3b80b2edfa1c8 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 14:37:41 -0300 Subject: [PATCH 48/52] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81ef45c475..c3d0a4b937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,3 +10,10 @@ * Public Api changes: * `VirtualMachineError` enum variants containing `MaybeRelocatable` and/or `Relocatable` values now use the `Display` format instead of `Debug` in their `Display` implementation * `get_traceback` now adds the source code line to each traceback entry + +* Use hint location instead of instruction location when building VmExceptions from hint failure [#673](https://github.com/lambdaclass/cairo-rs/pull/673/files) + * Public Api changes: + * `hints` field added to `InstructionLocation` + * `Program.instruction_locations` type changed from `Option>` to `Option>` + * `VirtualMachineError`s produced by `HintProcessor::execute_hint()` will be wrapped in a `VirtualMachineError::Hint` error containing their hint_index + * `get_location()` now receives an an optional usize value `hint_index`, used to obtain hint locations From 68f73843f68012bc5ba7c968bbaa84e4a613d1fb Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 16:09:10 -0300 Subject: [PATCH 49/52] Finnish changing hint fns to HintError --- .../builtin_hint_processor/blake2s_utils.rs | 45 ++-- .../builtin_hint_processor_definition.rs | 36 ++- .../cairo_keccak/keccak_hints.rs | 55 ++-- .../builtin_hint_processor/dict_hint_utils.rs | 55 ++-- .../builtin_hint_processor/dict_manager.rs | 42 ++- .../find_element_hint.rs | 83 +++--- .../builtin_hint_processor/hint_utils.rs | 32 +-- .../builtin_hint_processor/keccak_utils.rs | 21 +- .../builtin_hint_processor/math_utils.rs | 248 +++++++++--------- .../memcpy_hint_utils.rs | 21 +- .../builtin_hint_processor/memset_utils.rs | 20 +- .../builtin_hint_processor/pow_utils.rs | 19 +- .../secp/bigint_utils.rs | 13 +- .../builtin_hint_processor/secp/ec_utils.rs | 32 +-- .../secp/field_utils.rs | 49 ++-- .../builtin_hint_processor/secp/secp_utils.rs | 24 +- .../builtin_hint_processor/secp/signature.rs | 45 ++-- .../builtin_hint_processor/segments.rs | 8 +- .../builtin_hint_processor/set.rs | 15 +- .../builtin_hint_processor/sha256_utils.rs | 7 +- .../squash_dict_utils.rs | 85 +++--- .../builtin_hint_processor/uint256_utils.rs | 41 +-- .../hint_processor_definition.rs | 3 +- src/hint_processor/hint_processor_utils.rs | 6 +- src/u.cairo | 23 -- src/vm/errors/hint_errors.rs | 24 +- src/vm/errors/vm_errors.rs | 22 +- 27 files changed, 521 insertions(+), 553 deletions(-) delete mode 100644 src/u.cairo diff --git a/src/hint_processor/builtin_hint_processor/blake2s_utils.rs b/src/hint_processor/builtin_hint_processor/blake2s_utils.rs index 38ed5730c7..9cc983b35d 100644 --- a/src/hint_processor/builtin_hint_processor/blake2s_utils.rs +++ b/src/hint_processor/builtin_hint_processor/blake2s_utils.rs @@ -6,6 +6,7 @@ use crate::hint_processor::builtin_hint_processor::hint_utils::{ }; use crate::hint_processor::hint_processor_definition::HintReference; use crate::hint_processor::hint_processor_utils::bigint_to_u32; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_traits::ToPrimitive; use std::borrow::Cow; @@ -18,14 +19,14 @@ use num_bigint::BigInt; fn get_fixed_size_u32_array( h_range: &Vec>, -) -> Result<[u32; T], VirtualMachineError> { +) -> Result<[u32; T], HintError> { let mut u32_vec = Vec::::with_capacity(h_range.len()); for num in h_range { - u32_vec.push(num.to_u32().ok_or(VirtualMachineError::BigintToU32Fail)?); + u32_vec.push(num.to_u32().ok_or(HintError::BigintToU32Fail)?); } u32_vec .try_into() - .map_err(|_| VirtualMachineError::FixedSizeArrayFail(T)) + .map_err(|_| HintError::FixedSizeArrayFail(T)) } fn get_maybe_relocatable_array_from_u32(array: &Vec) -> Vec { @@ -44,10 +45,7 @@ Computes the blake2s compress function and fills the value in the right position output_ptr should point to the middle of an instance, right after initial_state, message, t, f, which should all have a value at this point, and right before the output portion which will be written by this function.*/ -fn compute_blake2s_func( - vm: &mut VirtualMachine, - output_rel: Relocatable, -) -> Result<(), VirtualMachineError> { +fn compute_blake2s_func(vm: &mut VirtualMachine, output_rel: Relocatable) -> Result<(), HintError> { let h = get_fixed_size_u32_array::<8>(&vm.get_integer_range(&(output_rel.sub(26)?), 8)?)?; let message = get_fixed_size_u32_array::<16>(&vm.get_integer_range(&(output_rel.sub(18)?), 16)?)?; @@ -69,7 +67,7 @@ pub fn compute_blake2s( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let output = get_ptr_from_var_name("output", vm, ids_data, ap_tracking)?; compute_blake2s_func(vm, output) } @@ -100,7 +98,7 @@ pub fn finalize_blake2s( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { const N_PACKED_INSTANCES: usize = 7; let blake2s_ptr_end = get_ptr_from_var_name("blake2s_ptr_end", vm, ids_data, ap_tracking)?; let message: [u32; 16] = [0; 16]; @@ -132,7 +130,7 @@ pub fn blake2s_add_uint256( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Get variables from ids let data_ptr = get_ptr_from_var_name("data", vm, ids_data, ap_tracking)?; let low_addr = get_relocatable_from_var_name("low", vm, ids_data, ap_tracking)?; @@ -179,7 +177,7 @@ pub fn blake2s_add_uint256_bigend( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Get variables from ids let data_ptr = get_ptr_from_var_name("data", vm, ids_data, ap_tracking)?; let low_addr = get_relocatable_from_var_name("low", vm, ids_data, ap_tracking)?; @@ -225,6 +223,7 @@ mod tests { use crate::relocatable; use crate::types::exec_scope::ExecutionScopes; use crate::utils::test_utils::*; + use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use crate::vm::vm_memory::memory::Memory; use crate::{bigint, vm::errors::memory_errors::MemoryError}; @@ -247,7 +246,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::CantSubOffset(5, 26)) + Err(HintError::Internal(VirtualMachineError::CantSubOffset( + 5, 26 + ))) ); } @@ -266,9 +267,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((2, 0)) - )) + ))) ); } @@ -286,8 +287,8 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedRelocatable( - MaybeRelocatable::from((1, 0)) + Err(HintError::Internal( + VirtualMachineError::ExpectedRelocatable(MaybeRelocatable::from((1, 0))) )) ); } @@ -316,7 +317,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::BigintToU32Fail) + Err(HintError::BigintToU32Fail) ); } @@ -334,9 +335,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((2, 0)) - )) + ))) ); } @@ -398,13 +399,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((2, 0)), MaybeRelocatable::from((2, 0)), MaybeRelocatable::from(bigint!(1795745351)) ) - )) + ))) ); } @@ -418,7 +419,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 5fc572306f..1e0c58e48e 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -92,7 +92,7 @@ pub struct HintFunc( &HashMap, &ApTracking, &HashMap, - ) -> Result<(), VirtualMachineError> + ) -> Result<(), HintError> + Sync, >, ); @@ -436,7 +436,7 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::TEMPORARY_ARRAY => { temporary_array(vm, &hint_data.ids_data, &hint_data.ap_tracking) } - code => Err(VirtualMachineError::UnknownHint(code.to_string())), + code => Err(HintError::UnknownHint(code.to_string())), } } @@ -464,12 +464,12 @@ fn get_ids_data( let name = path .rsplit('.') .next() - .ok_or(VirtualMachineError::FailedToGetIds)?; + .ok_or(VirtualMachineError::Unexpected)?; ids_data.insert( name.to_string(), references .get(ref_id) - .ok_or(VirtualMachineError::FailedToGetIds)? + .ok_or(VirtualMachineError::Unexpected)? .clone(), ); } @@ -531,13 +531,13 @@ mod tests { //ids and references are not needed for this test assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 6)), MaybeRelocatable::from((1, 6)), MaybeRelocatable::from((3, 0)) ) - )) + ))) ); } @@ -547,7 +547,7 @@ mod tests { let mut vm = vm!(); assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::UnknownHint(hint_code.to_string())), + Err(HintError::UnknownHint(hint_code.to_string())), ); } @@ -580,9 +580,9 @@ mod tests { let ids_data = ids_data!["len"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 1)) - )) + ))) ); } @@ -617,9 +617,7 @@ mod tests { let ids_data = ids_data!["continue_copying"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::VariableNotInScopeError( - "n".to_string() - )) + Err(HintError::VariableNotInScopeError("n".to_string())) ); } @@ -640,13 +638,13 @@ mod tests { let ids_data = ids_data!["continue_copying"]; assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 1)), MaybeRelocatable::from(bigint!(5)), MaybeRelocatable::from(bigint!(0)) ) - )) + ))) ); } @@ -672,7 +670,7 @@ mod tests { add_segments!(vm, 1); assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::MainScopeError( + Err(HintError::FromScopeError( ExecScopeError::ExitMainScopeError )) ); @@ -737,7 +735,7 @@ mod tests { let mut exec_scopes = scope![("__keccak_max_size", bigint!(2))]; assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::KeccakMaxSize(bigint!(5), bigint!(2))) + Err(HintError::KeccakMaxSize(bigint!(5), bigint!(2))) ); } @@ -783,7 +781,7 @@ mod tests { let mut exec_scopes = scope![("__keccak_max_size", bigint!(10))]; assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::InvalidWordSize(bigint!(-1))) + Err(HintError::InvalidWordSize(bigint!(-1))) ); } @@ -825,7 +823,7 @@ mod tests { let ids_data = non_continuous_ids_data![("keccak_state", -7), ("high", -3), ("low", -2)]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::NoneInMemoryRange) + Err(HintError::Internal(VirtualMachineError::NoneInMemoryRange)) ); } @@ -855,7 +853,7 @@ mod tests { _ids_data: &HashMap, _ap_tracking: &ApTracking, _constants: &HashMap, - ) -> Result<(), VirtualMachineError> { + ) -> Result<(), HintError> { exec_scopes.enter_scope(HashMap::new()); Ok(()) } diff --git a/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs b/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs index 7c8e07238d..3264922b5b 100644 --- a/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs +++ b/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs @@ -1,6 +1,7 @@ use crate::hint_processor::builtin_hint_processor::hint_utils::get_integer_from_var_name; use crate::hint_processor::builtin_hint_processor::hint_utils::get_ptr_from_var_name; use crate::hint_processor::builtin_hint_processor::hint_utils::insert_value_into_ap; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use crate::{ bigint, hint_processor::hint_processor_definition::HintReference, @@ -34,7 +35,7 @@ pub fn keccak_write_args( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let inputs_ptr = get_ptr_from_var_name("inputs", vm, ids_data, ap_tracking)?; let low = get_integer_from_var_name("low", vm, ids_data, ap_tracking)?; @@ -69,7 +70,7 @@ pub fn compare_bytes_in_word_nondet( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let n_bytes = get_integer_from_var_name("n_bytes", vm, ids_data, ap_tracking)?; let n_bytes = n_bytes.as_ref(); @@ -80,7 +81,7 @@ pub fn compare_bytes_in_word_nondet( // bigint!(BYTES_INTO_WORD) into a lazy_static! let bytes_in_word = constants .get(BYTES_IN_WORD) - .ok_or(VirtualMachineError::MissingConstant(BYTES_IN_WORD))?; + .ok_or(HintError::MissingConstant(BYTES_IN_WORD))?; let value = bigint!((n_bytes < bytes_in_word) as usize); insert_value_into_ap(vm, value) } @@ -98,16 +99,13 @@ pub fn compare_keccak_full_rate_in_bytes_nondet( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let n_bytes = get_integer_from_var_name("n_bytes", vm, ids_data, ap_tracking)?; let n_bytes = n_bytes.as_ref(); - let keccak_full_rate_in_bytes = - constants - .get(KECCAK_FULL_RATE_IN_BYTES) - .ok_or(VirtualMachineError::MissingConstant( - KECCAK_FULL_RATE_IN_BYTES, - ))?; + let keccak_full_rate_in_bytes = constants + .get(KECCAK_FULL_RATE_IN_BYTES) + .ok_or(HintError::MissingConstant(KECCAK_FULL_RATE_IN_BYTES))?; let value = bigint!((n_bytes >= keccak_full_rate_in_bytes) as usize); insert_value_into_ap(vm, value) } @@ -129,16 +127,13 @@ pub fn block_permutation( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { - let keccak_state_size_felts = - constants - .get(KECCAK_STATE_SIZE_FELTS) - .ok_or(VirtualMachineError::MissingConstant( - KECCAK_STATE_SIZE_FELTS, - ))?; +) -> Result<(), HintError> { + let keccak_state_size_felts = constants + .get(KECCAK_STATE_SIZE_FELTS) + .ok_or(HintError::MissingConstant(KECCAK_STATE_SIZE_FELTS))?; if keccak_state_size_felts >= &bigint!(100) { - return Err(VirtualMachineError::InvalidKeccakStateSizeFelts( + return Err(HintError::InvalidKeccakStateSizeFelts( keccak_state_size_felts.clone(), )); } @@ -186,25 +181,22 @@ pub fn cairo_keccak_finalize( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { - let keccak_state_size_felts = - constants - .get(KECCAK_STATE_SIZE_FELTS) - .ok_or(VirtualMachineError::MissingConstant( - KECCAK_STATE_SIZE_FELTS, - ))?; +) -> Result<(), HintError> { + let keccak_state_size_felts = constants + .get(KECCAK_STATE_SIZE_FELTS) + .ok_or(HintError::MissingConstant(KECCAK_STATE_SIZE_FELTS))?; let block_size = constants .get(BLOCK_SIZE) - .ok_or(VirtualMachineError::MissingConstant(BLOCK_SIZE))?; + .ok_or(HintError::MissingConstant(BLOCK_SIZE))?; if keccak_state_size_felts >= &bigint!(100) { - return Err(VirtualMachineError::InvalidKeccakStateSizeFelts( + return Err(HintError::InvalidKeccakStateSizeFelts( keccak_state_size_felts.clone(), )); } if block_size >= &bigint!(10) { - return Err(VirtualMachineError::InvalidBlockSize(block_size.clone())); + return Err(HintError::InvalidBlockSize(block_size.clone())); } let keccak_state_size_felts = keccak_state_size_felts.to_usize().unwrap(); @@ -236,7 +228,7 @@ pub fn cairo_keccak_finalize( // of u64. Raises error if there are None's or if MaybeRelocatables are not Bigints. pub(crate) fn maybe_reloc_vec_to_u64_array( vec: &[Option>], -) -> Result, VirtualMachineError> { +) -> Result, HintError> { let array = vec .iter() .map(|n| match n { @@ -302,7 +294,10 @@ mod tests { //Create ids let ids_data = ids_data!["low", "high", "inputs"]; let error = run_hint!(vm, ids_data, hint_code); - assert!(matches!(error, Err(VirtualMachineError::MemoryError(_)))); + assert!(matches!( + error, + Err(HintError::Internal(VirtualMachineError::MemoryError(_))) + )); } #[test] diff --git a/src/hint_processor/builtin_hint_processor/dict_hint_utils.rs b/src/hint_processor/builtin_hint_processor/dict_hint_utils.rs index 4d8b9afe26..990bc712ca 100644 --- a/src/hint_processor/builtin_hint_processor/dict_hint_utils.rs +++ b/src/hint_processor/builtin_hint_processor/dict_hint_utils.rs @@ -1,4 +1,7 @@ -use crate::{types::exec_scope::ExecutionScopes, vm::vm_core::VirtualMachine}; +use crate::{ + types::exec_scope::ExecutionScopes, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, +}; use std::{any::Any, cell::RefCell, collections::HashMap, rc::Rc}; use num_bigint::BigInt; @@ -13,7 +16,6 @@ use crate::{ hint_processor_definition::HintReference, }, serde::deserialize_program::ApTracking, - vm::errors::vm_errors::VirtualMachineError, }; use super::dict_manager::DictManager; @@ -45,9 +47,9 @@ is not available pub fn dict_new( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Get initial dictionary from scope (defined by an earlier hint) - let initial_dict = copy_initial_dict(exec_scopes).ok_or(VirtualMachineError::NoInitialDict)?; + let initial_dict = copy_initial_dict(exec_scopes).ok_or(HintError::NoInitialDict)?; //Check if there is a dict manager in scope, create it if there isnt one let base = if let Ok(dict_manager) = exec_scopes.get_dict_manager() { dict_manager.borrow_mut().new_dict(vm, initial_dict)? @@ -75,7 +77,7 @@ pub fn default_dict_new( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that ids contains the reference id for each variable used by the hint let default_value = get_integer_from_var_name("default_value", vm, ids_data, ap_tracking)?.into_owned(); @@ -105,7 +107,7 @@ pub fn dict_read( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let key = get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; let key = key.as_ref(); let dict_ptr = get_ptr_from_var_name("dict_ptr", vm, ids_data, ap_tracking)?; @@ -128,7 +130,7 @@ pub fn dict_write( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let key = get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; let new_value = get_integer_from_var_name("new_value", vm, ids_data, ap_tracking)?; let key = key.as_ref(); @@ -169,7 +171,7 @@ pub fn dict_update( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let key = get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; let prev_value = get_integer_from_var_name("prev_value", vm, ids_data, ap_tracking)?; let new_value = get_integer_from_var_name("new_value", vm, ids_data, ap_tracking)?; @@ -182,7 +184,7 @@ pub fn dict_update( //Check that prev_value is equal to the current value at the given key let current_value = tracker.get_value(key.as_ref())?; if current_value != prev_value.as_ref() { - return Err(VirtualMachineError::WrongPrevValue( + return Err(HintError::WrongPrevValue( prev_value.into_owned(), current_value.clone(), key.into_owned(), @@ -209,7 +211,7 @@ pub fn dict_squash_copy_dict( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let dict_accesses_end = get_ptr_from_var_name("dict_accesses_end", vm, ids_data, ap_tracking)?; let dict_manager_ref = exec_scopes.get_dict_manager()?; let dict_manager = dict_manager_ref.borrow(); @@ -238,7 +240,7 @@ pub fn dict_squash_update_ptr( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let squashed_dict_start = get_ptr_from_var_name("squashed_dict_start", vm, ids_data, ap_tracking)?; let squashed_dict_end = get_ptr_from_var_name("squashed_dict_end", vm, ids_data, ap_tracking)?; @@ -257,6 +259,7 @@ mod tests { use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; use crate::hint_processor::hint_processor_definition::HintProcessor; use crate::types::exec_scope::ExecutionScopes; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_memory::memory::Memory; use std::collections::HashMap; @@ -307,7 +310,7 @@ mod tests { //ids and references are not needed for this test assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::NoInitialDict) + Err(HintError::NoInitialDict) ); } @@ -320,13 +323,13 @@ mod tests { //ids and references are not needed for this test assert_eq!( run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 0)), MaybeRelocatable::from(bigint!(1)), MaybeRelocatable::from((0, 0)) ) - )) + ))) ); } @@ -371,7 +374,7 @@ mod tests { dict_manager!(&mut exec_scopes, 2, (5, 12)); assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NoValueForKey(bigint!(6))) + Err(HintError::NoValueForKey(bigint!(6))) ); } #[test] @@ -390,7 +393,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NoDictTracker(2)) + Err(HintError::NoDictTracker(2)) ); } @@ -434,9 +437,9 @@ mod tests { let ids_data = ids_data!["default_value"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 0)) - )) + ))) ); } @@ -542,7 +545,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NoValueForKey(bigint!(5))) + Err(HintError::NoValueForKey(bigint!(5))) ); } @@ -613,7 +616,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::WrongPrevValue( + Err(HintError::WrongPrevValue( bigint!(11), bigint!(10), bigint!(5) @@ -640,7 +643,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NoValueForKey(bigint!(6),)) + Err(HintError::NoValueForKey(bigint!(6),)) ); } @@ -711,7 +714,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::WrongPrevValue( + Err(HintError::WrongPrevValue( bigint!(11), bigint!(10), bigint!(5) @@ -738,7 +741,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::WrongPrevValue( + Err(HintError::WrongPrevValue( bigint!(10), bigint!(17), bigint!(6) @@ -845,7 +848,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NoDictTracker(2)) + Err(HintError::NoDictTracker(2)) ); } @@ -865,7 +868,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NoDictTracker(2)) + Err(HintError::NoDictTracker(2)) ); } @@ -903,7 +906,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::MismatchedDictPtr( + Err(HintError::MismatchedDictPtr( relocatable!(2, 0), relocatable!(2, 3) )) diff --git a/src/hint_processor/builtin_hint_processor/dict_manager.rs b/src/hint_processor/builtin_hint_processor/dict_manager.rs index 249b35349b..1357457d5e 100644 --- a/src/hint_processor/builtin_hint_processor/dict_manager.rs +++ b/src/hint_processor/builtin_hint_processor/dict_manager.rs @@ -7,7 +7,9 @@ use num_traits::Signed; use crate::{ types::relocatable::{MaybeRelocatable, Relocatable}, vm::{ - errors::{memory_errors::MemoryError, vm_errors::VirtualMachineError}, + errors::{ + hint_errors::HintError, memory_errors::MemoryError, vm_errors::VirtualMachineError, + }, vm_core::VirtualMachine, }, }; @@ -76,18 +78,18 @@ impl DictManager { &mut self, vm: &mut VirtualMachine, initial_dict: HashMap, - ) -> Result { + ) -> Result { let base = vm.add_memory_segment(); if self.trackers.contains_key(&base.segment_index) { - return Err(VirtualMachineError::CantCreateDictionaryOnTakenSegment( + return Err(HintError::CantCreateDictionaryOnTakenSegment( base.segment_index, )); } if base.segment_index < 0 { - return Err(VirtualMachineError::MemoryError( + Err(VirtualMachineError::MemoryError( MemoryError::AddressInTemporarySegment(base.segment_index), - )); + ))?; }; let floored_initial = initial_dict @@ -117,10 +119,10 @@ impl DictManager { vm: &mut VirtualMachine, default_value: &BigInt, initial_dict: Option>, - ) -> Result { + ) -> Result { let base = vm.add_memory_segment(); if self.trackers.contains_key(&base.segment_index) { - return Err(VirtualMachineError::CantCreateDictionaryOnTakenSegment( + return Err(HintError::CantCreateDictionaryOnTakenSegment( base.segment_index, )); } @@ -135,31 +137,25 @@ impl DictManager { pub fn get_tracker_mut( &mut self, dict_ptr: &Relocatable, - ) -> Result<&mut DictTracker, VirtualMachineError> { + ) -> Result<&mut DictTracker, HintError> { let tracker = self .trackers .get_mut(&dict_ptr.segment_index) - .ok_or(VirtualMachineError::NoDictTracker(dict_ptr.segment_index))?; + .ok_or(HintError::NoDictTracker(dict_ptr.segment_index))?; if tracker.current_ptr != *dict_ptr { - return Err(VirtualMachineError::MismatchedDictPtr( - tracker.current_ptr, - *dict_ptr, - )); + return Err(HintError::MismatchedDictPtr(tracker.current_ptr, *dict_ptr)); } Ok(tracker) } //Returns the tracker which's current_ptr matches with the given dict_ptr - pub fn get_tracker(&self, dict_ptr: &Relocatable) -> Result<&DictTracker, VirtualMachineError> { + pub fn get_tracker(&self, dict_ptr: &Relocatable) -> Result<&DictTracker, HintError> { let tracker = self .trackers .get(&dict_ptr.segment_index) - .ok_or(VirtualMachineError::NoDictTracker(dict_ptr.segment_index))?; + .ok_or(HintError::NoDictTracker(dict_ptr.segment_index))?; if tracker.current_ptr != *dict_ptr { - return Err(VirtualMachineError::MismatchedDictPtr( - tracker.current_ptr, - *dict_ptr, - )); + return Err(HintError::MismatchedDictPtr(tracker.current_ptr, *dict_ptr)); } Ok(tracker) } @@ -215,10 +211,10 @@ impl DictTracker { } } - pub fn get_value(&mut self, key: &BigInt) -> Result<&BigInt, VirtualMachineError> { + pub fn get_value(&mut self, key: &BigInt) -> Result<&BigInt, HintError> { self.data .get(key) - .ok_or_else(|| VirtualMachineError::NoValueForKey(key.clone())) + .ok_or_else(|| HintError::NoValueForKey(key.clone())) } pub fn insert_value(&mut self, key: &BigInt, val: &BigInt) { @@ -342,7 +338,7 @@ mod tests { let mut vm = vm!(); assert_eq!( dict_manager.new_dict(&mut vm, HashMap::new()), - Err(VirtualMachineError::CantCreateDictionaryOnTakenSegment(0)) + Err(HintError::CantCreateDictionaryOnTakenSegment(0)) ); } @@ -356,7 +352,7 @@ mod tests { let mut vm = vm!(); assert_eq!( dict_manager.new_dict(&mut vm, HashMap::new()), - Err(VirtualMachineError::CantCreateDictionaryOnTakenSegment(0)) + Err(HintError::CantCreateDictionaryOnTakenSegment(0)) ); } diff --git a/src/hint_processor/builtin_hint_processor/find_element_hint.rs b/src/hint_processor/builtin_hint_processor/find_element_hint.rs index 19cdd59f57..33d125bd64 100644 --- a/src/hint_processor/builtin_hint_processor/find_element_hint.rs +++ b/src/hint_processor/builtin_hint_processor/find_element_hint.rs @@ -10,7 +10,10 @@ use crate::{ }, serde::deserialize_program::ApTracking, types::exec_scope::ExecutionScopes, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{ + errors::{hint_errors::HintError, vm_errors::VirtualMachineError}, + vm_core::VirtualMachine, + }, }; use num_bigint::BigInt; use num_traits::{Signed, ToPrimitive}; @@ -21,7 +24,7 @@ pub fn find_element( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let key = get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; let elm_size_bigint = get_integer_from_var_name("elm_size", vm, ids_data, ap_tracking)?; let n_elms = get_integer_from_var_name("n_elms", vm, ids_data, ap_tracking)?; @@ -29,21 +32,19 @@ pub fn find_element( let find_element_index = exec_scopes.get::("find_element_index").ok(); let elm_size = elm_size_bigint .to_usize() - .ok_or_else(|| VirtualMachineError::ValueOutOfRange(elm_size_bigint.as_ref().clone()))?; + .ok_or_else(|| HintError::ValueOutOfRange(elm_size_bigint.as_ref().clone()))?; if elm_size == 0 { - return Err(VirtualMachineError::ValueOutOfRange( - elm_size_bigint.into_owned(), - )); + return Err(HintError::ValueOutOfRange(elm_size_bigint.into_owned())); } if let Some(find_element_index_value) = find_element_index { let find_element_index_usize = bigint_to_usize(&find_element_index_value)?; let found_key = vm .get_integer(&(array_start + (elm_size * find_element_index_usize))) - .map_err(|_| VirtualMachineError::KeyNotFound)?; + .map_err(|_| HintError::KeyNotFound)?; if found_key.as_ref() != key.as_ref() { - return Err(VirtualMachineError::InvalidIndex( + return Err(HintError::InvalidIndex( find_element_index_value, key.into_owned(), found_key.into_owned(), @@ -54,12 +55,12 @@ pub fn find_element( Ok(()) } else { if n_elms.is_negative() { - return Err(VirtualMachineError::ValueOutOfRange(n_elms.into_owned())); + return Err(HintError::ValueOutOfRange(n_elms.into_owned())); } if let Ok(find_element_max_size) = exec_scopes.get_ref::("find_element_max_size") { if n_elms.as_ref() > find_element_max_size { - return Err(VirtualMachineError::FindElemMaxSize( + return Err(HintError::FindElemMaxSize( find_element_max_size.clone(), n_elms.into_owned(), )); @@ -72,14 +73,14 @@ pub fn find_element( for i in 0..n_elms_iter { let iter_key = vm .get_integer(&(array_start + (elm_size * i as usize))) - .map_err(|_| VirtualMachineError::KeyNotFound)?; + .map_err(|_| HintError::KeyNotFound)?; if iter_key.as_ref() == key.as_ref() { return insert_value_from_var_name("index", bigint!(i), vm, ids_data, ap_tracking); } } - Err(VirtualMachineError::NoValueForKey(key.into_owned())) + Err(HintError::NoValueForKey(key.into_owned())) } } @@ -88,7 +89,7 @@ pub fn search_sorted_lower( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let find_element_max_size = exec_scopes.get::("find_element_max_size"); let n_elms = get_integer_from_var_name("n_elms", vm, ids_data, ap_tracking)?; let rel_array_ptr = get_relocatable_from_var_name("array_ptr", vm, ids_data, ap_tracking)?; @@ -96,16 +97,16 @@ pub fn search_sorted_lower( let key = get_integer_from_var_name("key", vm, ids_data, ap_tracking)?; if !elm_size.is_positive() { - return Err(VirtualMachineError::ValueOutOfRange(elm_size.into_owned())); + return Err(HintError::ValueOutOfRange(elm_size.into_owned())); } if n_elms.is_negative() { - return Err(VirtualMachineError::ValueOutOfRange(n_elms.into_owned())); + return Err(HintError::ValueOutOfRange(n_elms.into_owned())); } if let Ok(find_element_max_size) = find_element_max_size { if n_elms.as_ref() > &find_element_max_size { - return Err(VirtualMachineError::FindElemMaxSize( + return Err(HintError::FindElemMaxSize( find_element_max_size, n_elms.into_owned(), )); @@ -113,10 +114,8 @@ pub fn search_sorted_lower( } let mut array_iter = vm.get_relocatable(&rel_array_ptr)?; - let n_elms_usize = n_elms.to_usize().ok_or(VirtualMachineError::KeyNotFound)?; - let elm_size_usize = elm_size - .to_usize() - .ok_or(VirtualMachineError::KeyNotFound)?; + let n_elms_usize = n_elms.to_usize().ok_or(HintError::KeyNotFound)?; + let elm_size_usize = elm_size.to_usize().ok_or(HintError::KeyNotFound)?; for i in 0..n_elms_usize { let value = vm.get_integer(&array_iter)?; @@ -239,7 +238,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::NoValueForKey(bigint!(7))) + Err(HintError::NoValueForKey(bigint!(7))) ); } @@ -249,7 +248,7 @@ mod tests { let mut exec_scopes = scope![("find_element_index", bigint!(2))]; assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT, &mut exec_scopes), - Err(VirtualMachineError::KeyNotFound) + Err(HintError::KeyNotFound) ); } @@ -260,9 +259,9 @@ mod tests { let ids_data = ids_data!["array_ptr", "elm_size", "n_elms", "index", "key"]; assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 4)) - )) + ))) ); } @@ -274,9 +273,9 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 1)) - )) + ))) ); } @@ -288,7 +287,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ValueOutOfRange(bigint!(0))) + Err(HintError::ValueOutOfRange(bigint!(0))) ); } @@ -300,7 +299,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ValueOutOfRange(bigint!(-1))) + Err(HintError::ValueOutOfRange(bigint!(-1))) ); } @@ -311,7 +310,9 @@ mod tests { init_vm_ids_data(HashMap::from([("n_elms".to_string(), relocatable.clone())])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ExpectedInteger(relocatable)) + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( + relocatable + ))) ); } @@ -323,7 +324,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ValueOutOfRange(bigint!(-1))) + Err(HintError::ValueOutOfRange(bigint!(-1))) ); } @@ -339,7 +340,7 @@ mod tests { let mut exec_scopes = scope![("find_element_max_size", bigint!(1))]; assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT, &mut exec_scopes), - Err(VirtualMachineError::FindElemMaxSize(bigint!(1), bigint!(2))) + Err(HintError::FindElemMaxSize(bigint!(1), bigint!(2))) ); } @@ -350,7 +351,9 @@ mod tests { init_vm_ids_data(HashMap::from([("key".to_string(), relocatable.clone())])); assert_eq!( run_hint!(vm, ids_data, hint_code::FIND_ELEMENT), - Err(VirtualMachineError::ExpectedInteger(relocatable)) + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( + relocatable + ))) ); } @@ -386,9 +389,9 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 1)) - )) + ))) ); } @@ -400,7 +403,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), - Err(VirtualMachineError::ValueOutOfRange(bigint!(0))) + Err(HintError::ValueOutOfRange(bigint!(0))) ); } @@ -412,7 +415,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), - Err(VirtualMachineError::ValueOutOfRange(bigint!(-1))) + Err(HintError::ValueOutOfRange(bigint!(-1))) ); } @@ -424,9 +427,9 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 2)) - )) + ))) ); } @@ -438,7 +441,7 @@ mod tests { )])); assert_eq!( run_hint!(vm, ids_data, hint_code::SEARCH_SORTED_LOWER), - Err(VirtualMachineError::ValueOutOfRange(bigint!(-1))) + Err(HintError::ValueOutOfRange(bigint!(-1))) ); } @@ -462,7 +465,7 @@ mod tests { hint_code::SEARCH_SORTED_LOWER, &mut exec_scopes ), - Err(VirtualMachineError::FindElemMaxSize(bigint!(1), bigint!(2))) + Err(HintError::FindElemMaxSize(bigint!(1), bigint!(2))) ); } } diff --git a/src/hint_processor/builtin_hint_processor/hint_utils.rs b/src/hint_processor/builtin_hint_processor/hint_utils.rs index b2cf857a94..54c98dfb32 100644 --- a/src/hint_processor/builtin_hint_processor/hint_utils.rs +++ b/src/hint_processor/builtin_hint_processor/hint_utils.rs @@ -4,7 +4,7 @@ use crate::hint_processor::hint_processor_utils::get_integer_from_reference; use crate::serde::deserialize_program::ApTracking; use crate::types::relocatable::MaybeRelocatable; use crate::types::relocatable::Relocatable; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use std::borrow::Cow; @@ -17,17 +17,19 @@ pub fn insert_value_from_var_name( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let var_address = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?; vm.insert_value(&var_address, value) + .map_err(HintError::Internal) } //Inserts value into ap pub fn insert_value_into_ap( vm: &mut VirtualMachine, value: impl Into, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { vm.insert_value(&vm.get_ap(), value) + .map_err(HintError::Internal) } //Returns the Relocatable value stored in the given ids variable @@ -36,12 +38,12 @@ pub fn get_ptr_from_var_name( vm: &VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result { +) -> Result { let var_addr = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?; //Add immediate if present in reference let hint_reference = ids_data .get(&String::from(var_name)) - .ok_or(VirtualMachineError::FailedToGetIds)?; + .ok_or(HintError::FailedToGetIds)?; if hint_reference.dereference { let value = vm.get_relocatable(&var_addr)?; Ok(value) @@ -56,11 +58,9 @@ pub fn get_address_from_var_name( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result { +) -> Result { Ok(MaybeRelocatable::from(compute_addr_from_reference( - ids_data - .get(var_name) - .ok_or(VirtualMachineError::FailedToGetIds)?, + ids_data.get(var_name).ok_or(HintError::FailedToGetIds)?, vm, ap_tracking, )?)) @@ -72,11 +72,9 @@ pub fn get_relocatable_from_var_name( vm: &VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result { +) -> Result { compute_addr_from_reference( - ids_data - .get(var_name) - .ok_or(VirtualMachineError::FailedToGetIds)?, + ids_data.get(var_name).ok_or(HintError::FailedToGetIds)?, vm, ap_tracking, ) @@ -90,7 +88,7 @@ pub fn get_integer_from_var_name<'a>( vm: &'a VirtualMachine, ids_data: &'a HashMap, ap_tracking: &ApTracking, -) -> Result, VirtualMachineError> { +) -> Result, HintError> { let reference = get_reference_from_var_name(var_name, ids_data)?; get_integer_from_reference(vm, reference, ap_tracking) } @@ -98,10 +96,8 @@ pub fn get_integer_from_var_name<'a>( pub fn get_reference_from_var_name<'a>( var_name: &str, ids_data: &'a HashMap, -) -> Result<&'a HintReference, VirtualMachineError> { - ids_data - .get(var_name) - .ok_or(VirtualMachineError::FailedToGetIds) +) -> Result<&'a HintReference, HintError> { + ids_data.get(var_name).ok_or(HintError::FailedToGetIds) } #[cfg(test)] diff --git a/src/hint_processor/builtin_hint_processor/keccak_utils.rs b/src/hint_processor/builtin_hint_processor/keccak_utils.rs index fcdf62bb54..369c4b84f4 100644 --- a/src/hint_processor/builtin_hint_processor/keccak_utils.rs +++ b/src/hint_processor/builtin_hint_processor/keccak_utils.rs @@ -11,7 +11,10 @@ use crate::{ exec_scope::ExecutionScopes, relocatable::{MaybeRelocatable, Relocatable}, }, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{ + errors::{hint_errors::HintError, vm_errors::VirtualMachineError}, + vm_core::VirtualMachine, + }, }; use num_bigint::{BigInt, Sign}; use num_traits::Signed; @@ -47,12 +50,12 @@ pub fn unsafe_keccak( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let length = get_integer_from_var_name("length", vm, ids_data, ap_tracking)?; if let Ok(keccak_max_size) = exec_scopes.get::("__keccak_max_size") { if length.as_ref() > &keccak_max_size { - return Err(VirtualMachineError::KeccakMaxSize( + return Err(HintError::KeccakMaxSize( length.into_owned(), keccak_max_size, )); @@ -68,7 +71,7 @@ pub fn unsafe_keccak( // transform to u64 to make ranges cleaner in the for loop below let u64_length = length .to_u64() - .ok_or_else(|| VirtualMachineError::InvalidKeccakInputLength(length.into_owned()))?; + .ok_or_else(|| HintError::InvalidKeccakInputLength(length.into_owned()))?; let mut keccak_input = Vec::new(); for (word_i, byte_i) in (0..u64_length).step_by(16).enumerate() { @@ -81,7 +84,7 @@ pub fn unsafe_keccak( let n_bytes = cmp::min(16, u64_length - byte_i); if word.is_negative() || word.as_ref() >= &bigint!(1).shl(8 * (n_bytes as u32)) { - return Err(VirtualMachineError::InvalidWordSize(word.into_owned())); + return Err(HintError::InvalidWordSize(word.into_owned())); } let (_, mut bytes) = word.to_bytes_be(); @@ -102,7 +105,8 @@ pub fn unsafe_keccak( let low = BigInt::from_bytes_be(Sign::Plus, &hashed[16..32]); vm.insert_value(&high_addr, &high)?; - vm.insert_value(&low_addr, &low) + vm.insert_value(&low_addr, &low)?; + Ok(()) } /* @@ -124,7 +128,7 @@ pub fn unsafe_keccak_finalize( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { /* ----------------------------- Just for reference (cairo code): struct KeccakState: @@ -189,7 +193,8 @@ pub fn unsafe_keccak_finalize( let low = BigInt::from_bytes_be(Sign::Plus, &hashed[16..32]); vm.insert_value(&high_addr, &high)?; - vm.insert_value(&low_addr, &low) + vm.insert_value(&low_addr, &low)?; + Ok(()) } fn left_pad(bytes_vector: &mut [u8], n_zeros: usize) -> Vec { diff --git a/src/hint_processor/builtin_hint_processor/math_utils.rs b/src/hint_processor/builtin_hint_processor/math_utils.rs index 80a740ebaa..4b56a49869 100644 --- a/src/hint_processor/builtin_hint_processor/math_utils.rs +++ b/src/hint_processor/builtin_hint_processor/math_utils.rs @@ -10,7 +10,10 @@ use crate::{ math_utils::{as_int, isqrt}, serde::deserialize_program::ApTracking, types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable}, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{ + errors::{hint_errors::HintError, vm_errors::VirtualMachineError}, + vm_core::VirtualMachine, + }, }; use std::{ @@ -28,7 +31,7 @@ pub fn is_nn( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let range_check_builtin = vm.get_range_check_builtin()?; //Main logic (assert a is not negative and within the expected range) @@ -47,7 +50,7 @@ pub fn is_nn_out_of_range( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let a = a.as_ref(); let range_check_builtin = vm.get_range_check_builtin()?; @@ -74,16 +77,16 @@ pub fn assert_le_felt( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { const PRIME_OVER_3_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH"; const PRIME_OVER_2_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH"; let prime_over_3_high = constants .get(PRIME_OVER_3_HIGH) - .ok_or(VirtualMachineError::MissingConstant(PRIME_OVER_3_HIGH))?; + .ok_or(HintError::MissingConstant(PRIME_OVER_3_HIGH))?; let prime_over_2_high = constants .get(PRIME_OVER_2_HIGH) - .ok_or(VirtualMachineError::MissingConstant(PRIME_OVER_2_HIGH))?; + .ok_or(HintError::MissingConstant(PRIME_OVER_2_HIGH))?; let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)? .clone() .into_owned(); @@ -93,7 +96,7 @@ pub fn assert_le_felt( let range_check_ptr = get_ptr_from_var_name("range_check_ptr", vm, ids_data, ap_tracking)?; if a.mod_floor(vm.get_prime()) > b.mod_floor(vm.get_prime()) { - return Err(VirtualMachineError::NonLeFelt(a.clone(), b.clone())); + return Err(HintError::NonLeFelt(a.clone(), b.clone())); } let arc1 = b - a; @@ -103,7 +106,7 @@ pub fn assert_le_felt( if lengths_and_indices[0].0 > &(vm.get_prime() / 3) || lengths_and_indices[1].0 > &(vm.get_prime() / 2) { - return Err(VirtualMachineError::ArcTooBig( + return Err(HintError::ArcTooBig( lengths_and_indices[0].0.clone(), vm.get_prime() / 3, lengths_and_indices[1].0.clone(), @@ -120,16 +123,15 @@ pub fn assert_le_felt( vm.insert_value(&(&range_check_ptr + 1), q_0)?; vm.insert_value(&range_check_ptr, r_0)?; vm.insert_value(&(&range_check_ptr + 3), q_1)?; - vm.insert_value(&(&range_check_ptr + 2), r_1) + vm.insert_value(&(&range_check_ptr + 2), r_1)?; + Ok(()) } -pub fn assert_le_felt_excluded_2( - exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +pub fn assert_le_felt_excluded_2(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { let excluded: BigInt = exec_scopes.get("excluded")?; if excluded != bigint!(2) { - Err(VirtualMachineError::ExcludedNot2(excluded)) + Err(HintError::ExcludedNot2(excluded)) } else { Ok(()) } @@ -138,7 +140,7 @@ pub fn assert_le_felt_excluded_2( pub fn assert_le_felt_excluded_1( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let excluded: BigInt = exec_scopes.get("excluded")?; if excluded != bigint!(1) { @@ -151,7 +153,7 @@ pub fn assert_le_felt_excluded_1( pub fn assert_le_felt_excluded_0( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let excluded: BigInt = exec_scopes.get("excluded")?; if !excluded.is_zero() { @@ -167,7 +169,7 @@ pub fn is_le_felt( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a_mod = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?.mod_floor(vm.get_prime()); let b_mod = @@ -192,7 +194,7 @@ pub fn assert_not_equal( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a_addr = get_address_from_var_name("a", vm, ids_data, ap_tracking)?; let b_addr = get_address_from_var_name("b", vm, ids_data, ap_tracking)?; //Check that the ids are in memory @@ -203,7 +205,7 @@ pub fn assert_not_equal( match (maybe_rel_a, maybe_rel_b) { (MaybeRelocatable::Int(a), MaybeRelocatable::Int(b)) => { if (&a - &b).is_multiple_of(vm.get_prime()) { - return Err(VirtualMachineError::AssertNotEqualFail( + return Err(HintError::AssertNotEqualFail( MaybeRelocatable::Int(a), MaybeRelocatable::Int(b), )); @@ -212,10 +214,10 @@ pub fn assert_not_equal( } (MaybeRelocatable::RelocatableValue(a), MaybeRelocatable::RelocatableValue(b)) => { if a.segment_index != b.segment_index { - return Err(VirtualMachineError::DiffIndexComp(a, b)); + Err(VirtualMachineError::DiffIndexComp(a, b))?; }; if a.offset == b.offset { - return Err(VirtualMachineError::AssertNotEqualFail( + return Err(HintError::AssertNotEqualFail( MaybeRelocatable::RelocatableValue(a), MaybeRelocatable::RelocatableValue(b), )); @@ -225,10 +227,10 @@ pub fn assert_not_equal( (maybe_rel_a, maybe_rel_b) => Err(VirtualMachineError::DiffTypeComparison( maybe_rel_a, maybe_rel_b, - )), + ))?, } } - _ => Err(VirtualMachineError::FailedToGetIds), + _ => Err(HintError::FailedToGetIds), } } @@ -242,13 +244,13 @@ pub fn assert_nn( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let range_check_builtin = vm.get_range_check_builtin()?; // assert 0 <= ids.a % PRIME < range_check_builtin.bound // as prime > 0, a % prime will always be > 0 if a.mod_floor(vm.get_prime()) >= range_check_builtin._bound { - return Err(VirtualMachineError::ValueOutOfRange(a.into_owned())); + return Err(HintError::AssertNNValueOutOfRange(a.into_owned())); }; Ok(()) } @@ -263,10 +265,10 @@ pub fn assert_not_zero( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; if value.is_multiple_of(vm.get_prime()) { - return Err(VirtualMachineError::AssertNotZero( + return Err(HintError::AssertNotZero( value.into_owned(), vm.get_prime().clone(), )); @@ -279,11 +281,11 @@ pub fn split_int_assert_range( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; //Main logic (assert value == 0) if !value.is_zero() { - return Err(VirtualMachineError::SplitIntNotZero); + return Err(HintError::SplitIntNotZero); } Ok(()) } @@ -294,7 +296,7 @@ pub fn split_int( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let base = get_integer_from_var_name("base", vm, ids_data, ap_tracking)?; let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?; @@ -304,9 +306,9 @@ pub fn split_int( //Main Logic let res = (value.mod_floor(vm.get_prime())).mod_floor(base); if &res > bound { - return Err(VirtualMachineError::SplitIntLimbOutOfRange(res)); + return Err(HintError::SplitIntLimbOutOfRange(res)); } - vm.insert_value(&output, res) + vm.insert_value(&output, res).map_err(HintError::Internal) } //from starkware.cairo.common.math_utils import is_positive @@ -316,14 +318,14 @@ pub fn is_positive( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let value = value.as_ref(); let range_check_builtin = vm.get_range_check_builtin()?; //Main logic (assert a is positive) let int_value = as_int(value, vm.get_prime()); if int_value.abs() > range_check_builtin._bound { - return Err(VirtualMachineError::ValueOutsideValidRange(int_value)); + return Err(HintError::ValueOutsideValidRange(int_value)); } let result = if int_value.is_positive() { bigint!(1) @@ -346,7 +348,7 @@ pub fn split_felt( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let value = value.as_ref(); //Main logic @@ -368,12 +370,12 @@ pub fn sqrt( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let mod_value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?.mod_floor(vm.get_prime()); //This is equal to mod_value > bigint!(2).pow(250) if (&mod_value).shr(250_i32).is_positive() { - return Err(VirtualMachineError::ValueOutside250BitRange(mod_value)); + return Err(HintError::ValueOutside250BitRange(mod_value)); } insert_value_from_var_name("root", isqrt(&mod_value)?, vm, ids_data, ap_tracking) } @@ -382,7 +384,7 @@ pub fn signed_div_rem( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?; let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let value = value.as_ref(); @@ -390,14 +392,14 @@ pub fn signed_div_rem( let builtin = vm.get_range_check_builtin()?; // Main logic if !div.is_positive() || div.as_ref() > &(vm.get_prime() / &builtin._bound) { - return Err(VirtualMachineError::OutOfValidRange( + return Err(HintError::OutOfValidRange( div.into_owned(), vm.get_prime() / &builtin._bound, )); } // Divide by 2 if bound.as_ref() > &(&builtin._bound).shr(1_i32) { - return Err(VirtualMachineError::OutOfValidRange( + return Err(HintError::OutOfValidRange( bound.into_owned(), (&builtin._bound).shr(1_i32), )); @@ -406,7 +408,7 @@ pub fn signed_div_rem( let int_value = &as_int(value, vm.get_prime()); let (q, r) = int_value.div_mod_floor(div.as_ref()); if bound.as_ref().neg() > q || &q >= bound.as_ref() { - return Err(VirtualMachineError::OutOfValidRange(q, bound.into_owned())); + return Err(HintError::OutOfValidRange(q, bound.into_owned())); } let biased_q = q + bound.as_ref(); insert_value_from_var_name("r", r, vm, ids_data, ap_tracking)?; @@ -426,13 +428,13 @@ pub fn unsigned_div_rem( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?; let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; let builtin = vm.get_range_check_builtin()?; // Main logic if !div.is_positive() || div.as_ref() > &(vm.get_prime() / &builtin._bound) { - return Err(VirtualMachineError::OutOfValidRange( + return Err(HintError::OutOfValidRange( div.into_owned(), vm.get_prime() / &builtin._bound, )); @@ -452,7 +454,7 @@ pub fn assert_250_bit( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Declare constant values let upper_bound = bigint!(1).shl(250_i32); let shift = bigint!(1).shl(128_i32); @@ -460,7 +462,7 @@ pub fn assert_250_bit( //Main logic let int_value = as_int(value.as_ref(), vm.get_prime()).mod_floor(vm.get_prime()); if int_value > upper_bound { - return Err(VirtualMachineError::ValueOutside250BitRange(int_value)); + return Err(HintError::ValueOutside250BitRange(int_value)); } let (high, low) = int_value.div_rem(&shift); insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?; @@ -481,7 +483,7 @@ pub fn assert_lt_felt( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?; // Main logic @@ -490,10 +492,7 @@ pub fn assert_lt_felt( // assert (ids.a % PRIME) < (ids.b % PRIME), \ // f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.' if a.mod_floor(vm.get_prime()) >= b.mod_floor(vm.get_prime()) { - return Err(VirtualMachineError::AssertLtFelt( - a.into_owned(), - b.into_owned(), - )); + return Err(HintError::AssertLtFelt(a.into_owned(), b.into_owned())); }; Ok(()) } @@ -592,7 +591,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::NoRangeCheckBuiltin) + Err(HintError::Internal( + VirtualMachineError::NoRangeCheckBuiltin + )) ); } @@ -607,7 +608,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -624,9 +625,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 4)) - )) + ))) ); } @@ -643,9 +644,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 4)) - )) + ))) ); } @@ -706,13 +707,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 0)), MaybeRelocatable::Int(bigint!(1)), MaybeRelocatable::Int(bigint!(0)) ) - )) + ))) ); } @@ -726,7 +727,7 @@ mod tests { let ids_data = ids_data!["a", "c"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -758,7 +759,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ValueOutOfRange(bigint!(-1))) + Err(HintError::AssertNNValueOutOfRange(bigint!(-1))) ); } @@ -774,7 +775,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds), + Err(HintError::FailedToGetIds), ); } @@ -790,9 +791,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 3)) - )) + ))) ); } @@ -808,7 +809,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::NoRangeCheckBuiltin) + Err(HintError::Internal( + VirtualMachineError::NoRangeCheckBuiltin + )) ); } @@ -823,9 +826,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 3)) - )) + ))) ); } @@ -852,7 +855,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes, &constants), - Err(VirtualMachineError::NonLeFelt(bigint!(2), bigint!(1))) + Err(HintError::NonLeFelt(bigint!(2), bigint!(1))) ); } @@ -878,9 +881,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes, &constants), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 0)) - )) + ))) ); } @@ -906,9 +909,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes, &constants), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 1)) - )) + ))) ); } @@ -957,7 +960,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertNotEqualFail( + Err(HintError::AssertNotEqualFail( MaybeRelocatable::from(bigint!(1)), MaybeRelocatable::from(bigint!(1)) )) @@ -999,7 +1002,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertNotEqualFail( + Err(HintError::AssertNotEqualFail( MaybeRelocatable::from(bigint!(-1)), MaybeRelocatable::from(bigint_str!( b"3618502788666131213697322783095070105623107215331596699973092056135872020480" @@ -1020,7 +1023,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertNotEqualFail( + Err(HintError::AssertNotEqualFail( MaybeRelocatable::from((1, 0)), MaybeRelocatable::from((1, 0)) )) @@ -1052,10 +1055,10 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::DiffIndexComp( + Err(HintError::Internal(VirtualMachineError::DiffIndexComp( relocatable!(2, 0), relocatable!(1, 0) - )) + ))) ); } @@ -1071,9 +1074,11 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::DiffTypeComparison( - MaybeRelocatable::from((1, 0)), - MaybeRelocatable::from(bigint!(1)) + Err(HintError::Internal( + VirtualMachineError::DiffTypeComparison( + MaybeRelocatable::from((1, 0)), + MaybeRelocatable::from(bigint!(1)) + ) )) ); } @@ -1106,7 +1111,7 @@ mod tests { let ids_data = ids_data!["value"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertNotZero(bigint!(0), vm.prime)) + Err(HintError::AssertNotZero(bigint!(0), vm.prime)) ); } @@ -1130,10 +1135,7 @@ mod tests { let ids_data = ids_data!["value"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertNotZero( - vm.prime.clone(), - vm.prime - )) + Err(HintError::AssertNotZero(vm.prime.clone(), vm.prime)) ); } @@ -1150,7 +1152,7 @@ mod tests { let ids_data = ids_data!["incorrect_id"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -1167,9 +1169,9 @@ mod tests { let ids_data = ids_data!["value"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 4)) - )) + ))) ); } @@ -1185,7 +1187,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::SplitIntNotZero) + Err(HintError::SplitIntNotZero) ); } @@ -1235,7 +1237,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::SplitIntLimbOutOfRange(bigint!(100))) + Err(HintError::SplitIntLimbOutOfRange(bigint!(100))) ); } @@ -1294,7 +1296,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ValueOutsideValidRange(as_int( + Err(HintError::ValueOutsideValidRange(as_int( &BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217727]), &vm.prime ))) @@ -1314,13 +1316,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 1)), MaybeRelocatable::from(bigint!(4)), MaybeRelocatable::from(bigint!(1)) ) - )) + ))) ); } @@ -1353,7 +1355,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ValueOutside250BitRange(bigint_str!( + Err(HintError::ValueOutside250BitRange(bigint_str!( b"3618502788666131213697322783095070105623107215331596699973092056135872020400" ))) ); @@ -1372,13 +1374,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 1)), MaybeRelocatable::from(bigint!(7)), MaybeRelocatable::from(bigint!(9)) ) - )) + ))) ); } @@ -1410,7 +1412,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::OutOfValidRange( + Err(HintError::OutOfValidRange( bigint!(-5), bigint_str!(b"10633823966279327296825105735305134080") )) @@ -1429,7 +1431,9 @@ mod tests { let ids_data = ids_data!["r", "q", "div", "value"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::NoRangeCheckBuiltin) + Err(HintError::Internal( + VirtualMachineError::NoRangeCheckBuiltin + )) ); } @@ -1446,13 +1450,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 0)), MaybeRelocatable::Int(bigint!(5)), MaybeRelocatable::Int(bigint!(2)) ) - )) + ))) ); } @@ -1469,7 +1473,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ) } @@ -1516,7 +1520,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::OutOfValidRange( + Err(HintError::OutOfValidRange( bigint!(-5), bigint_str!(b"10633823966279327296825105735305134080") )) @@ -1535,7 +1539,9 @@ mod tests { let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::NoRangeCheckBuiltin) + Err(HintError::Internal( + VirtualMachineError::NoRangeCheckBuiltin + )) ); } @@ -1552,13 +1558,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 1)), MaybeRelocatable::Int(bigint!(10)), MaybeRelocatable::Int(bigint!(31)) ) - )) + ))) ); } @@ -1575,7 +1581,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ) } @@ -1616,9 +1622,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ValueOutside250BitRange( - bigint!(1).shl(251i32) - )) + Err(HintError::ValueOutside250BitRange(bigint!(1).shl(251i32))) ); } @@ -1667,7 +1671,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -1693,13 +1697,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((2, 0)), MaybeRelocatable::from(bigint!(99)), MaybeRelocatable::from(bigint_str!(b"189509265092725080168209675610990602697")) ) - )) + ))) ); } @@ -1725,13 +1729,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((2, 1)), MaybeRelocatable::from(bigint!(99)), MaybeRelocatable::from(bigint!(21)) ) - )) + ))) ); } @@ -1752,9 +1756,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 3)) - )) + ))) ); } @@ -1785,7 +1789,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertLtFelt(bigint!(3), bigint!(2))) + Err(HintError::AssertLtFelt(bigint!(3), bigint!(2))) ); } @@ -1802,7 +1806,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -1818,9 +1822,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 1)) - )) + ))) ); } @@ -1836,9 +1840,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 2)) - )) + ))) ); } @@ -1855,9 +1859,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 2)) - )) + ))) ); } } diff --git a/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs b/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs index d2168cee35..db6d6333b5 100644 --- a/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs +++ b/src/hint_processor/builtin_hint_processor/memcpy_hint_utils.rs @@ -8,30 +8,28 @@ use crate::{ }, serde::deserialize_program::ApTracking, types::exec_scope::ExecutionScopes, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; use num_bigint::BigInt; use num_traits::Signed; use std::{any::Any, collections::HashMap}; //Implements hint: memory[ap] = segments.add() -pub fn add_segment(vm: &mut VirtualMachine) -> Result<(), VirtualMachineError> { +pub fn add_segment(vm: &mut VirtualMachine) -> Result<(), HintError> { let new_segment_base = vm.add_memory_segment(); insert_value_into_ap(vm, new_segment_base) } //Implements hint: vm_enter_scope() -pub fn enter_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), VirtualMachineError> { +pub fn enter_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { exec_scopes.enter_scope(HashMap::new()); Ok(()) } // Implements hint: // %{ vm_exit_scope() %} -pub fn exit_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), VirtualMachineError> { - exec_scopes - .exit_scope() - .map_err(VirtualMachineError::MainScopeError) +pub fn exit_scope(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { + exec_scopes.exit_scope().map_err(HintError::FromScopeError) } // Implements hint: @@ -41,7 +39,7 @@ pub fn memcpy_enter_scope( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let len: Box = Box::new(get_integer_from_var_name("len", vm, ids_data, ap_tracking)?.into_owned()); exec_scopes.enter_scope(HashMap::from([(String::from("n"), len)])); @@ -58,7 +56,7 @@ pub fn memcpy_continue_copying( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { // get `n` variable from vm scope let n = exec_scopes.get_ref::("n")?; // this variable will hold the value of `n - 1` @@ -81,6 +79,7 @@ mod tests { use crate::types::relocatable::MaybeRelocatable; use crate::utils::test_utils::*; use crate::vm::errors::memory_errors::MemoryError; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; use crate::vm::vm_memory::memory::Memory; use num_bigint::BigInt; @@ -128,9 +127,9 @@ mod tests { assert_eq!( get_integer_from_var_name(var_name, &vm, &ids_data, &ApTracking::default()), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 0)) - )) + ))) ); } } diff --git a/src/hint_processor/builtin_hint_processor/memset_utils.rs b/src/hint_processor/builtin_hint_processor/memset_utils.rs index 17c400ae85..08410dd782 100644 --- a/src/hint_processor/builtin_hint_processor/memset_utils.rs +++ b/src/hint_processor/builtin_hint_processor/memset_utils.rs @@ -8,7 +8,7 @@ use crate::{ }, serde::deserialize_program::ApTracking, types::exec_scope::ExecutionScopes, - vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; use num_bigint::BigInt; use num_traits::Signed; @@ -21,7 +21,7 @@ pub fn memset_enter_scope( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let n: Box = Box::new(get_integer_from_var_name("n", vm, ids_data, ap_tracking)?.into_owned()); exec_scopes.enter_scope(HashMap::from([(String::from("n"), n)])); @@ -39,7 +39,7 @@ pub fn memset_continue_loop( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { // get `n` variable from vm scope let n = exec_scopes.get_ref::("n")?; // this variable will hold the value of `n - 1` @@ -63,6 +63,8 @@ mod tests { use crate::hint_processor::hint_processor_definition::HintProcessor; use crate::types::exec_scope::ExecutionScopes; use crate::utils::test_utils::*; + use crate::vm::errors::hint_errors::HintError; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_memory::memory::Memory; use crate::{ types::relocatable::MaybeRelocatable, @@ -94,9 +96,9 @@ mod tests { let ids_data = ids_data!["n"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 1)) - )) + ))) ); } @@ -152,9 +154,7 @@ mod tests { let ids_data = ids_data!["continue_loop"]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::VariableNotInScopeError( - "n".to_string() - )) + Err(HintError::VariableNotInScopeError("n".to_string())) ); } @@ -172,13 +172,13 @@ mod tests { let ids_data = ids_data!["continue_loop"]; assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 0)), MaybeRelocatable::from(bigint!(5)), MaybeRelocatable::from(bigint!(0)) ) - )) + ))) ); } } diff --git a/src/hint_processor/builtin_hint_processor/pow_utils.rs b/src/hint_processor/builtin_hint_processor/pow_utils.rs index f2eb5e8ee5..fb16d2b360 100644 --- a/src/hint_processor/builtin_hint_processor/pow_utils.rs +++ b/src/hint_processor/builtin_hint_processor/pow_utils.rs @@ -2,7 +2,7 @@ use crate::hint_processor::builtin_hint_processor::hint_utils::{ get_relocatable_from_var_name, insert_value_from_var_name, }; use crate::serde::deserialize_program::ApTracking; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use crate::{bigint, hint_processor::hint_processor_definition::HintReference}; use num_bigint::BigInt; @@ -17,7 +17,7 @@ pub fn pow( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let prev_locs_addr = get_relocatable_from_var_name("prev_locs", vm, ids_data, ap_tracking)?; let prev_locs_exp = vm.get_integer(&(&prev_locs_addr + 4))?; let locs_bit = prev_locs_exp.mod_floor(vm.get_prime()) & bigint!(1); @@ -36,6 +36,7 @@ mod tests { use crate::types::relocatable::MaybeRelocatable; use crate::utils::test_utils::*; use crate::vm::errors::memory_errors::MemoryError; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; use crate::vm::vm_memory::memory::Memory; use crate::{bigint, vm::runners::builtin_runner::RangeCheckBuiltinRunner}; @@ -69,7 +70,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::FailedToGetIds) + Err(HintError::FailedToGetIds) ); } @@ -85,9 +86,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 10)) - )) + ))) ); } @@ -105,9 +106,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 10)) - )) + ))) ); } @@ -124,13 +125,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 11)), MaybeRelocatable::from(bigint!(3)), MaybeRelocatable::from(bigint!(1)) ) - )) + ))) ); } } diff --git a/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs b/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs index 373b0af814..d75cf30aed 100644 --- a/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs @@ -8,6 +8,7 @@ use crate::hint_processor::hint_processor_definition::HintReference; use crate::serde::deserialize_program::ApTracking; use crate::types::exec_scope::ExecutionScopes; use crate::types::relocatable::MaybeRelocatable; +use crate::vm::errors::hint_errors::HintError; use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; @@ -28,7 +29,7 @@ pub fn nondet_bigint3( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let res_reloc = get_relocatable_from_var_name("res", vm, ids_data, ap_tracking)?; let value = exec_scopes.get_ref::("value")?; let arg: Vec = split(value, constants)? @@ -47,7 +48,7 @@ pub fn bigint_to_uint256( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let x_struct = get_relocatable_from_var_name("x", vm, ids_data, ap_tracking)?; let d0 = vm.get_integer(&x_struct)?; let d1 = vm.get_integer(&(&x_struct + 1))?; @@ -55,7 +56,7 @@ pub fn bigint_to_uint256( let d1 = d1.as_ref(); let base_86 = constants .get(BASE_86) - .ok_or(VirtualMachineError::MissingConstant(BASE_86))?; + .ok_or(HintError::MissingConstant(BASE_86))?; let low = (d0 + d1 * &*base_86) & bigint!(u128::MAX); insert_value_from_var_name("low", low, vm, ids_data, ap_tracking) } @@ -125,9 +126,7 @@ mod tests { let ids_data = non_continuous_ids_data![("res", 5)]; assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::VariableNotInScopeError( - "value".to_string() - )) + Err(HintError::VariableNotInScopeError("value".to_string())) ); } @@ -142,7 +141,7 @@ mod tests { let ids_data = non_continuous_ids_data![("res", 5)]; assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::SecpSplitNegative(bigint!(-1))) + Err(HintError::SecpSplitNegative(bigint!(-1))) ); } } diff --git a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs index 2020d2ed17..011a90af46 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -7,7 +7,7 @@ use crate::hint_processor::hint_processor_definition::HintReference; use crate::math_utils::{ec_double_slope, line_slope}; use crate::serde::deserialize_program::ApTracking; use crate::types::exec_scope::ExecutionScopes; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use num_integer::Integer; @@ -32,11 +32,11 @@ pub fn ec_negate( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //ids.point let point_y = get_relocatable_from_var_name("point", vm, ids_data, ap_tracking)? + 3; @@ -64,11 +64,11 @@ pub fn compute_doubling_slope( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //ids.point let point_reloc = get_relocatable_from_var_name("point", vm, ids_data, ap_tracking)?; @@ -115,11 +115,11 @@ pub fn compute_slope( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //ids.point0 let point0_reloc = get_relocatable_from_var_name("point0", vm, ids_data, ap_tracking)?; @@ -199,11 +199,11 @@ pub fn ec_double_assign_new_x( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //ids.slope let slope_reloc = get_relocatable_from_var_name("slope", vm, ids_data, ap_tracking)?; @@ -253,11 +253,11 @@ Implements hint: pub fn ec_double_assign_new_y( exec_scopes: &mut ExecutionScopes, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //Get variables from vm scope let (slope, x, new_x, y) = ( @@ -292,11 +292,11 @@ pub fn fast_ec_add_assign_new_x( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //ids.slope let slope_reloc = get_relocatable_from_var_name("slope", vm, ids_data, ap_tracking)?; @@ -372,11 +372,11 @@ Implements hint: pub fn fast_ec_add_assign_new_y( exec_scopes: &mut ExecutionScopes, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //Get variables from vm scope let (slope, x0, new_x, y0) = ( @@ -400,7 +400,7 @@ pub fn ec_mul_inner( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //(ids.scalar % PRIME) % 2 let scalar = get_integer_from_var_name("scalar", vm, ids_data, ap_tracking)? .mod_floor(vm.get_prime()) diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index db84ddb0a8..629a524a38 100644 --- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -7,7 +7,7 @@ use crate::hint_processor::hint_processor_definition::HintReference; use crate::math_utils::div_mod; use crate::serde::deserialize_program::ApTracking; use crate::types::exec_scope::ExecutionScopes; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use num_integer::Integer; @@ -32,17 +32,17 @@ pub fn verify_zero( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; let val = pack_from_var_name("val", vm, ids_data, ap_tracking)?; let (q, r) = val.div_rem(&secp_p); if !r.is_zero() { - return Err(VirtualMachineError::SecpVerifyZero(val)); + return Err(HintError::SecpVerifyZero(val)); } insert_value_from_var_name("q", q.mod_floor(vm.get_prime()), vm, ids_data, ap_tracking) @@ -62,11 +62,11 @@ pub fn reduce( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; let value = pack_from_var_name("x", vm, ids_data, ap_tracking)?.mod_floor(&secp_p); exec_scopes.insert_value("value", value); @@ -87,11 +87,11 @@ pub fn is_zero_pack( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; let x_packed = pack_from_var_name("x", vm, ids_data, ap_tracking)?; let x = x_packed.mod_floor(&secp_p); @@ -110,7 +110,7 @@ On .json compiled program pub fn is_zero_nondet( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Get `x` variable from vm scope let x = exec_scopes.get::("x")?; @@ -130,11 +130,11 @@ Implements hint: pub fn is_zero_assign_scope_variables( exec_scopes: &mut ExecutionScopes, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; //Get `x` variable from vm scope let x = exec_scopes.get::("x")?; @@ -159,6 +159,7 @@ mod tests { use crate::types::relocatable::Relocatable; use crate::utils::test_utils::*; use crate::vm::errors::memory_errors::MemoryError; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::runners::builtin_runner::RangeCheckBuiltinRunner; use crate::vm::vm_core::VirtualMachine; use crate::vm::vm_memory::memory::Memory; @@ -235,7 +236,7 @@ mod tests { .map(|(k, v)| (k.to_string(), v)) .collect() ), - Err(VirtualMachineError::SecpVerifyZero(bigint_str!( + Err(HintError::SecpVerifyZero(bigint_str!( b"897946605976106752944343961220884287276604954404454400" ),)) ); @@ -274,13 +275,13 @@ mod tests { .map(|(k, v)| (k.to_string(), v)) .collect() ), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 9)), MaybeRelocatable::from(bigint!(55)), MaybeRelocatable::from(bigint!(0)) ) - )) + ))) ); } @@ -369,9 +370,9 @@ mod tests { .map(|(k, v)| (k.to_string(), v)) .collect() ), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 20)) - )) + ))) ); } @@ -464,9 +465,9 @@ mod tests { .map(|(k, v)| (k.to_string(), v)) .collect() ), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 10)) - )) + ))) ); } @@ -538,9 +539,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::VariableNotInScopeError( - "x".to_string() - )) + Err(HintError::VariableNotInScopeError("x".to_string())) ); } @@ -561,13 +560,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from(vm.run_context.get_ap()), MaybeRelocatable::from(bigint!(55i32)), MaybeRelocatable::from(bigint!(1i32)) ) - )) + ))) ); } @@ -651,9 +650,7 @@ mod tests { .map(|(k, v)| (k.to_string(), v)) .collect() ), - Err(VirtualMachineError::VariableNotInScopeError( - "x".to_string() - )) + Err(HintError::VariableNotInScopeError("x".to_string())) ); } } diff --git a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs index 6d92abfba5..6fb3b721cf 100644 --- a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -2,7 +2,7 @@ use crate::hint_processor::hint_processor_definition::HintReference; use crate::math_utils::as_int; use crate::serde::deserialize_program::ApTracking; use crate::types::relocatable::Relocatable; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use crate::{ bigint, hint_processor::builtin_hint_processor::hint_utils::get_relocatable_from_var_name, @@ -30,14 +30,14 @@ where BASE = 2**86. pub fn split( integer: &BigInt, constants: &HashMap, -) -> Result<[BigInt; 3], VirtualMachineError> { +) -> Result<[BigInt; 3], HintError> { if integer.is_negative() { - return Err(VirtualMachineError::SecpSplitNegative(integer.clone())); + return Err(HintError::SecpSplitNegative(integer.clone())); } let base_86_max = constants .get(BASE_86) - .ok_or(VirtualMachineError::MissingConstant(BASE_86))? + .ok_or(HintError::MissingConstant(BASE_86))? - &bigint!(1); let mut num = integer.clone(); @@ -47,7 +47,7 @@ pub fn split( num >>= 86_usize; } if !num.is_zero() { - return Err(VirtualMachineError::SecpSplitutOfRange(integer.clone())); + return Err(HintError::SecpSplitutOfRange(integer.clone())); } Ok(canonical_repr) } @@ -73,7 +73,7 @@ pub fn pack_from_var_name( vm: &VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result { +) -> Result { let to_pack = get_relocatable_from_var_name(name, vm, ids_data, ap_tracking)?; let d0 = vm.get_integer(&to_pack)?; @@ -83,10 +83,7 @@ pub fn pack_from_var_name( Ok(pack(d0.as_ref(), d1.as_ref(), d2.as_ref(), vm.get_prime())) } -pub fn pack_from_relocatable( - rel: Relocatable, - vm: &VirtualMachine, -) -> Result { +pub fn pack_from_relocatable(rel: Relocatable, vm: &VirtualMachine) -> Result { let d0 = vm.get_integer(&rel)?; let d1 = vm.get_integer(&(&rel + 1))?; let d2 = vm.get_integer(&(&rel + 2))?; @@ -129,13 +126,10 @@ mod tests { bigint_str!(b"1292469707114105") ]) ); - assert_eq!( - array_4, - Err(VirtualMachineError::SecpSplitNegative(bigint!(-1))) - ); + assert_eq!(array_4, Err(HintError::SecpSplitNegative(bigint!(-1)))); assert_eq!( array_5, - Err(VirtualMachineError::SecpSplitutOfRange(bigint_str!( + Err(HintError::SecpSplitutOfRange(bigint_str!( b"773712524553362671811952647737125245533626718119526477371252455336267181195264" ))) ); diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index f33f8be23d..7789353d25 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -2,13 +2,13 @@ use super::secp_utils::{BASE_86, BETA, N0, N1, N2, SECP_REM}; use crate::hint_processor::builtin_hint_processor::hint_utils::get_integer_from_var_name; use crate::hint_processor::builtin_hint_processor::secp::secp_utils::pack_from_var_name; use crate::hint_processor::hint_processor_definition::HintReference; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use crate::{ bigint, math_utils::{div_mod, safe_div}, serde::deserialize_program::ApTracking, types::exec_scope::ExecutionScopes, - vm::errors::vm_errors::VirtualMachineError, }; use num_bigint::BigInt; use num_integer::Integer; @@ -29,23 +29,17 @@ pub fn div_mod_n_packed_divmod( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = pack_from_var_name("a", vm, ids_data, ap_tracking)?; let b = pack_from_var_name("b", vm, ids_data, ap_tracking)?; let n = { let base = constants .get(BASE_86) - .ok_or(VirtualMachineError::MissingConstant(BASE_86))?; - let n0 = constants - .get(N0) - .ok_or(VirtualMachineError::MissingConstant(N0))?; - let n1 = constants - .get(N1) - .ok_or(VirtualMachineError::MissingConstant(N1))?; - let n2 = constants - .get(N2) - .ok_or(VirtualMachineError::MissingConstant(N2))?; + .ok_or(HintError::MissingConstant(BASE_86))?; + let n0 = constants.get(N0).ok_or(HintError::MissingConstant(N0))?; + let n1 = constants.get(N1).ok_or(HintError::MissingConstant(N1))?; + let n2 = constants.get(N2).ok_or(HintError::MissingConstant(N2))?; (n2 * base * base) | (n1 * base) | n0 }; @@ -63,7 +57,7 @@ pub fn div_mod_n_packed_divmod( pub fn div_mod_n_safe_div( exec_scopes: &mut ExecutionScopes, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = exec_scopes.get_ref::("a")?; let b = exec_scopes.get_ref::("b")?; let res = exec_scopes.get_ref::("res")?; @@ -71,16 +65,10 @@ pub fn div_mod_n_safe_div( let n = { let base = constants .get(BASE_86) - .ok_or(VirtualMachineError::MissingConstant(BASE_86))?; - let n0 = constants - .get(N0) - .ok_or(VirtualMachineError::MissingConstant(N0))?; - let n1 = constants - .get(N1) - .ok_or(VirtualMachineError::MissingConstant(N1))?; - let n2 = constants - .get(N2) - .ok_or(VirtualMachineError::MissingConstant(N2))?; + .ok_or(HintError::MissingConstant(BASE_86))?; + let n0 = constants.get(N0).ok_or(HintError::MissingConstant(N0))?; + let n1 = constants.get(N1).ok_or(HintError::MissingConstant(N1))?; + let n2 = constants.get(N2).ok_or(HintError::MissingConstant(N2))?; n2 * base * base + n1 * base + n0 }; @@ -97,14 +85,14 @@ pub fn get_point_from_x( ids_data: &HashMap, ap_tracking: &ApTracking, constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let beta = constants .get(BETA) - .ok_or(VirtualMachineError::MissingConstant(BETA))?; + .ok_or(HintError::MissingConstant(BETA))?; let secp_p = bigint!(1).shl(256usize) - constants .get(SECP_REM) - .ok_or(VirtualMachineError::MissingConstant(SECP_REM))?; + .ok_or(HintError::MissingConstant(SECP_REM))?; let x_cube_int = pack_from_var_name("x_cube", vm, ids_data, ap_tracking)?.mod_floor(&secp_p); let y_cube_int = (x_cube_int + beta).mod_floor(&secp_p); @@ -126,6 +114,7 @@ mod tests { use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; use crate::hint_processor::builtin_hint_processor::hint_code; use crate::hint_processor::hint_processor_definition::HintProcessor; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::{ bigint, bigint_str, types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable}, @@ -175,11 +164,11 @@ mod tests { let mut exec_scopes = scope![("a", bigint!(0)), ("b", bigint!(1)), ("res", bigint!(1))]; assert_eq!( Err( - VirtualMachineError::SafeDivFail( + HintError::Internal(VirtualMachineError::SafeDivFail( bigint!(1_usize), bigint_str!(b"115792089237316195423570985008687907852837564279074904382605163141518161494337"), ) - ), + )), div_mod_n_safe_div( &mut exec_scopes, &[ diff --git a/src/hint_processor/builtin_hint_processor/segments.rs b/src/hint_processor/builtin_hint_processor/segments.rs index 3f62bceabf..e00a8fe844 100644 --- a/src/hint_processor/builtin_hint_processor/segments.rs +++ b/src/hint_processor/builtin_hint_processor/segments.rs @@ -5,6 +5,7 @@ use crate::hint_processor::{ use crate::serde::deserialize_program::ApTracking; +use crate::vm::errors::hint_errors::HintError; use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; @@ -20,11 +21,12 @@ pub fn relocate_segment( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let src_ptr = get_ptr_from_var_name("src_ptr", vm, ids_data, ap_tracking)?; let dest_ptr = get_ptr_from_var_name("dest_ptr", vm, ids_data, ap_tracking)?; - vm.add_relocation_rule(src_ptr, dest_ptr)?; + vm.add_relocation_rule(src_ptr, dest_ptr) + .map_err(VirtualMachineError::MemoryError)?; Ok(()) } @@ -39,7 +41,7 @@ pub fn temporary_array( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let temp_segment = vm.add_temporary_segment(); insert_value_from_var_name("temporary_array", temp_segment, vm, ids_data, ap_tracking)?; diff --git a/src/hint_processor/builtin_hint_processor/set.rs b/src/hint_processor/builtin_hint_processor/set.rs index 67732d2585..42fc0ed4ef 100644 --- a/src/hint_processor/builtin_hint_processor/set.rs +++ b/src/hint_processor/builtin_hint_processor/set.rs @@ -1,6 +1,7 @@ use crate::bigint; use crate::serde::deserialize_program::ApTracking; use crate::types::relocatable::MaybeRelocatable; +use crate::vm::errors::hint_errors::HintError; use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; @@ -16,7 +17,7 @@ pub fn set_add( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let set_ptr = get_ptr_from_var_name("set_ptr", vm, ids_data, ap_tracking)?; let elm_size = get_integer_from_var_name("elm_size", vm, ids_data, ap_tracking)? .to_usize() @@ -25,14 +26,14 @@ pub fn set_add( let set_end_ptr = get_ptr_from_var_name("set_end_ptr", vm, ids_data, ap_tracking)?; if elm_size.is_zero() { - return Err(VirtualMachineError::ValueNotPositive(bigint!(elm_size))); + Err(VirtualMachineError::ValueNotPositive(bigint!(elm_size)))?; } let elm = vm .get_range(&MaybeRelocatable::from(elm_ptr), elm_size) .map_err(VirtualMachineError::MemoryError)?; if set_ptr > set_end_ptr { - return Err(VirtualMachineError::InvalidSetRange( + return Err(HintError::InvalidSetRange( MaybeRelocatable::from(set_ptr), MaybeRelocatable::from(set_end_ptr), )); @@ -142,7 +143,7 @@ mod tests { let (mut vm, ids_data) = init_vm_ids_data(None, Some(-2), None, None); assert_eq!( run_hint!(vm, ids_data, HINT_CODE), - Err(VirtualMachineError::BigintToUsizeFail) + Err(HintError::Internal(VirtualMachineError::BigintToUsizeFail)) ); } @@ -152,7 +153,9 @@ mod tests { let (mut vm, ids_data) = init_vm_ids_data(None, Some(0), None, None); assert_eq!( run_hint!(vm, ids_data, HINT_CODE), - Err(VirtualMachineError::ValueNotPositive(int)) + Err(HintError::Internal(VirtualMachineError::ValueNotPositive( + int + ))) ); } #[test] @@ -160,7 +163,7 @@ mod tests { let (mut vm, ids_data) = init_vm_ids_data(Some((2, 3)), None, None, None); assert_eq!( run_hint!(vm, ids_data, HINT_CODE), - Err(VirtualMachineError::InvalidSetRange( + Err(HintError::InvalidSetRange( MaybeRelocatable::from((2, 3)), MaybeRelocatable::from((2, 2)), )) diff --git a/src/hint_processor/builtin_hint_processor/sha256_utils.rs b/src/hint_processor/builtin_hint_processor/sha256_utils.rs index eddeb44bca..6bde14c66c 100644 --- a/src/hint_processor/builtin_hint_processor/sha256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/sha256_utils.rs @@ -3,6 +3,7 @@ use crate::hint_processor::builtin_hint_processor::hint_utils::get_ptr_from_var_ use crate::hint_processor::builtin_hint_processor::hint_utils::insert_value_from_var_name; use crate::hint_processor::hint_processor_utils::bigint_to_u32; use crate::types::relocatable::MaybeRelocatable; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use crate::{ bigint, serde::deserialize_program::ApTracking, vm::errors::vm_errors::VirtualMachineError, @@ -27,7 +28,7 @@ pub fn sha256_input( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let n_bytes = get_integer_from_var_name("n_bytes", vm, ids_data, ap_tracking)?; let n_bytes = n_bytes.as_ref(); @@ -48,7 +49,7 @@ pub fn sha256_main( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let input_ptr = get_ptr_from_var_name("sha256_start", vm, ids_data, ap_tracking)?; let mut message: Vec = Vec::with_capacity(4 * SHA256_INPUT_CHUNK_SIZE_FELTS); @@ -80,7 +81,7 @@ pub fn sha256_finalize( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let message: Vec = vec![0; 64]; let mut iv = IV; diff --git a/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs b/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs index 498be23f8f..b5e451c36b 100644 --- a/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs +++ b/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs @@ -1,5 +1,6 @@ use crate::hint_processor::hint_processor_definition::HintReference; use crate::types::exec_scope::ExecutionScopes; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use num_integer::Integer; @@ -18,7 +19,7 @@ use crate::{ fn get_access_indices( exec_scopes: &mut ExecutionScopes, -) -> Result<&HashMap>, VirtualMachineError> { +) -> Result<&HashMap>, HintError> { let mut access_indices: Option<&HashMap>> = None; if let Some(variable) = exec_scopes .get_local_variables_mut()? @@ -28,8 +29,7 @@ fn get_access_indices( access_indices = Some(py_access_indices); } } - access_indices - .ok_or_else(|| VirtualMachineError::VariableNotInScopeError("access_indices".to_string())) + access_indices.ok_or_else(|| HintError::VariableNotInScopeError("access_indices".to_string())) } /*Implements hint: @@ -42,7 +42,7 @@ pub fn squash_dict_inner_first_iteration( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that access_indices and key are in scope let key = exec_scopes.get::("key")?; let range_check_ptr = get_ptr_from_var_name("range_check_ptr", vm, ids_data, ap_tracking)?; @@ -50,19 +50,20 @@ pub fn squash_dict_inner_first_iteration( //Get current_indices from access_indices let mut current_access_indices = access_indices .get(&key) - .ok_or_else(|| VirtualMachineError::NoKeyInAccessIndices(key.clone()))? + .ok_or_else(|| HintError::NoKeyInAccessIndices(key.clone()))? .clone(); current_access_indices.sort(); current_access_indices.reverse(); //Get current_access_index let first_val = current_access_indices .pop() - .ok_or(VirtualMachineError::EmptyCurrentAccessIndices)?; + .ok_or(HintError::EmptyCurrentAccessIndices)?; //Store variables in scope exec_scopes.insert_value("current_access_indices", current_access_indices); exec_scopes.insert_value("current_access_index", first_val.clone()); //Insert current_accesss_index into range_check_ptr vm.insert_value(&range_check_ptr, first_val) + .map_err(HintError::Internal) } // Implements Hint: ids.should_skip_loop = 0 if current_access_indices else 1 @@ -71,7 +72,7 @@ pub fn squash_dict_inner_skip_loop( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that current_access_indices is in scope let current_access_indices = exec_scopes.get_list_ref::("current_access_indices")?; //Main Logic @@ -99,7 +100,7 @@ pub fn squash_dict_inner_check_access_index( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that current_access_indices and current_access_index are in scope let current_access_index = exec_scopes.get::("current_access_index")?; let current_access_indices = @@ -107,7 +108,7 @@ pub fn squash_dict_inner_check_access_index( //Main Logic let new_access_index = current_access_indices .pop() - .ok_or(VirtualMachineError::EmptyCurrentAccessIndices)?; + .ok_or(HintError::EmptyCurrentAccessIndices)?; let index_delta_minus1 = new_access_index.clone() - current_access_index - bigint!(1); //loop_temps.delta_minus1 = loop_temps + 0 as it is the first field of the struct //Insert loop_temps.delta_minus1 into memory @@ -123,7 +124,7 @@ pub fn squash_dict_inner_continue_loop( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that ids contains the reference id for each variable used by the hint //Get addr for ids variables let loop_temps_addr = get_relocatable_from_var_name("loop_temps", vm, ids_data, ap_tracking)?; @@ -139,16 +140,15 @@ pub fn squash_dict_inner_continue_loop( //Insert loop_temps.delta_minus1 into memory let should_continue_addr = loop_temps_addr + 3; vm.insert_value(&should_continue_addr, should_continue) + .map_err(HintError::Internal) } // Implements Hint: assert len(current_access_indices) == 0 -pub fn squash_dict_inner_len_assert( - exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +pub fn squash_dict_inner_len_assert(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { //Check that current_access_indices is in scope let current_access_indices = exec_scopes.get_list_ref::("current_access_indices")?; if !current_access_indices.is_empty() { - return Err(VirtualMachineError::CurrentAccessIndicesNotEmpty); + return Err(HintError::CurrentAccessIndicesNotEmpty); } Ok(()) } @@ -159,17 +159,17 @@ pub fn squash_dict_inner_used_accesses_assert( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let key = exec_scopes.get::("key")?; let n_used_accesses = get_integer_from_var_name("n_used_accesses", vm, ids_data, ap_tracking)?; let access_indices = get_access_indices(exec_scopes)?; //Main Logic let access_indices_at_key = access_indices .get(&key) - .ok_or_else(|| VirtualMachineError::NoKeyInAccessIndices(key.clone()))?; + .ok_or_else(|| HintError::NoKeyInAccessIndices(key.clone()))?; if n_used_accesses.as_ref() != &bigint!(access_indices_at_key.len()) { - return Err(VirtualMachineError::NumUsedAccessesAssertFail( + return Err(HintError::NumUsedAccessesAssertFail( n_used_accesses.into_owned(), access_indices_at_key.len(), key, @@ -181,11 +181,11 @@ pub fn squash_dict_inner_used_accesses_assert( // Implements Hint: assert len(keys) == 0 pub fn squash_dict_inner_assert_len_keys( exec_scopes: &mut ExecutionScopes, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that current_access_indices is in scope let keys = exec_scopes.get_list_ref::("keys")?; if !keys.is_empty() { - return Err(VirtualMachineError::KeysNotEmpty); + return Err(HintError::KeysNotEmpty); }; Ok(()) } @@ -198,10 +198,10 @@ pub fn squash_dict_inner_next_key( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Check that current_access_indices is in scope let keys = exec_scopes.get_mut_list_ref::("keys")?; - let next_key = keys.pop().ok_or(VirtualMachineError::EmptyKeys)?; + let next_key = keys.pop().ok_or(HintError::EmptyKeys)?; //Insert next_key into ids.next_keys insert_value_from_var_name("next_key", next_key.clone(), vm, ids_data, ap_tracking)?; //Update local variables @@ -235,7 +235,7 @@ pub fn squash_dict( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { //Get necessary variables addresses from ids let address = get_ptr_from_var_name("dict_accesses", vm, ids_data, ap_tracking)?; let ptr_diff = get_integer_from_var_name("ptr_diff", vm, ids_data, ap_tracking)?; @@ -245,12 +245,12 @@ pub fn squash_dict( let range_check_bound = range_check_builtin._bound.clone(); //Main Logic if ptr_diff.mod_floor(&bigint!(DICT_ACCESS_SIZE)) != bigint!(0) { - return Err(VirtualMachineError::PtrDiffNotDivisibleByDictAccessSize); + return Err(HintError::PtrDiffNotDivisibleByDictAccessSize); } let squash_dict_max_size = exec_scopes.get::("__squash_dict_max_size"); if let Ok(max_size) = squash_dict_max_size { if n_accesses.as_ref() > &max_size { - return Err(VirtualMachineError::SquashDictMaxSizeExceeded( + return Err(HintError::SquashDictMaxSizeExceeded( max_size, n_accesses.into_owned(), )); @@ -258,7 +258,7 @@ pub fn squash_dict( }; let n_accesses_usize = n_accesses .to_usize() - .ok_or_else(|| VirtualMachineError::NAccessesTooBig(n_accesses.into_owned()))?; + .ok_or_else(|| HintError::NAccessesTooBig(n_accesses.into_owned()))?; //A map from key to the list of indices accessing it. let mut access_indices = HashMap::>::new(); for i in 0..n_accesses_usize { @@ -282,7 +282,7 @@ pub fn squash_dict( bigint!(0) }; insert_value_from_var_name("big_keys", big_keys, vm, ids_data, ap_tracking)?; - let key = keys.pop().ok_or(VirtualMachineError::EmptyKeys)?; + let key = keys.pop().ok_or(HintError::EmptyKeys)?; insert_value_from_var_name("first_key", key.clone(), vm, ids_data, ap_tracking)?; //Insert local variables into scope exec_scopes.insert_value("access_indices", access_indices); @@ -376,7 +376,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::EmptyCurrentAccessIndices) + Err(HintError::EmptyCurrentAccessIndices) ); } @@ -395,9 +395,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::VariableNotInScopeError(String::from( - "key" - ))) + Err(HintError::VariableNotInScopeError(String::from("key"))) ); } @@ -494,7 +492,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::EmptyCurrentAccessIndices) + Err(HintError::EmptyCurrentAccessIndices) ); } @@ -560,7 +558,7 @@ mod tests { //Hint should produce an error if assertion fails assert_eq!( run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes), - Err(VirtualMachineError::CurrentAccessIndicesNotEmpty) + Err(HintError::CurrentAccessIndicesNotEmpty) ); } @@ -606,7 +604,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::NumUsedAccessesAssertFail( + Err(HintError::NumUsedAccessesAssertFail( bigint!(5), 4, bigint!(5) @@ -634,9 +632,9 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::ExpectedInteger( + Err(HintError::Internal(VirtualMachineError::ExpectedInteger( MaybeRelocatable::from((1, 0)) - )) + ))) ); } @@ -664,7 +662,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes), - Err(VirtualMachineError::KeysNotEmpty) + Err(HintError::KeysNotEmpty) ); } @@ -676,9 +674,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, HashMap::new(), hint_code), - Err(VirtualMachineError::VariableNotInScopeError(String::from( - "keys" - ))) + Err(HintError::VariableNotInScopeError(String::from("keys"))) ); } @@ -719,7 +715,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::EmptyKeys) + Err(HintError::EmptyKeys) ); } @@ -909,10 +905,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code, &mut exec_scopes), - Err(VirtualMachineError::SquashDictMaxSizeExceeded( - bigint!(1), - bigint!(2) - )) + Err(HintError::SquashDictMaxSizeExceeded(bigint!(1), bigint!(2))) ); } @@ -947,7 +940,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::PtrDiffNotDivisibleByDictAccessSize) + Err(HintError::PtrDiffNotDivisibleByDictAccessSize) ); } #[test] @@ -987,7 +980,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::NAccessesTooBig(bigint_str!( + Err(HintError::NAccessesTooBig(bigint_str!( b"3618502761706184546546682988428055018603476541694452277432519575032261771265" ))) ); diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 9e86abefca..c9f3faa697 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -4,7 +4,7 @@ use crate::hint_processor::builtin_hint_processor::hint_utils::{ }; use crate::math_utils::isqrt; use crate::serde::deserialize_program::ApTracking; -use crate::vm::errors::vm_errors::VirtualMachineError; +use crate::vm::errors::hint_errors::HintError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use num_integer::{div_rem, Integer}; @@ -30,7 +30,7 @@ pub fn uint256_add( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let shift: BigInt = bigint!(2).pow(128); let a_relocatable = get_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?; @@ -76,7 +76,7 @@ pub fn split_64( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let mut digits = a.iter_u64_digits(); let low = bigint!(digits.next().unwrap_or(0u64)); @@ -104,7 +104,7 @@ pub fn uint256_sqrt( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let n_addr = get_relocatable_from_var_name("n", vm, ids_data, ap_tracking)?; let root_addr = get_relocatable_from_var_name("root", vm, ids_data, ap_tracking)?; let n_low = vm.get_integer(&n_addr)?; @@ -123,13 +123,14 @@ pub fn uint256_sqrt( let root = isqrt(&(n_high.shl(128_usize) + n_low))?; if root.is_negative() || root >= bigint!(1).shl(128) { - return Err(VirtualMachineError::AssertionFailed(format!( + return Err(HintError::AssertionFailed(format!( "assert 0 <= {} < 2 ** 128", &root ))); } vm.insert_value(&root_addr, root)?; vm.insert_value(&(root_addr + 1), bigint!(0)) + .map_err(HintError::Internal) } /* @@ -140,7 +141,7 @@ pub fn uint256_signed_nn( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a_addr = get_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?; let a_high = vm.get_integer(&(a_addr + 1))?; //Main logic @@ -171,7 +172,7 @@ pub fn uint256_unsigned_div_rem( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a_addr = get_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?; let div_addr = get_relocatable_from_var_name("div", vm, ids_data, ap_tracking)?; let quotient_addr = get_relocatable_from_var_name("quotient", vm, ids_data, ap_tracking)?; @@ -215,7 +216,8 @@ pub fn uint256_unsigned_div_rem( //Insert ids.remainder.low vm.insert_value(&remainder_addr, remainder_low)?; //Insert ids.remainder.high - vm.insert_value(&(remainder_addr + 1), remainder_high) + vm.insert_value(&(remainder_addr + 1), remainder_high)?; + Ok(()) } #[cfg(test)] @@ -231,6 +233,7 @@ mod tests { use crate::types::relocatable::Relocatable; use crate::utils::test_utils::*; use crate::vm::errors::memory_errors::MemoryError; + use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; use crate::vm::vm_memory::memory::Memory; use crate::{bigint, vm::runners::builtin_runner::RangeCheckBuiltinRunner}; @@ -280,13 +283,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 12)), MaybeRelocatable::from(bigint!(2)), MaybeRelocatable::from(bigint!(0)) ) - )) + ))) ); } @@ -349,13 +352,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 10)), MaybeRelocatable::from(bigint!(0)), MaybeRelocatable::from(bigint_str!(b"7249717543555297151")) ) - )) + ))) ); } @@ -390,7 +393,7 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::AssertionFailed(String::from( + Err(HintError::AssertionFailed(String::from( "assert 0 <= 340282366920938463463374607431768211456 < 2 ** 128" ))) ); @@ -409,13 +412,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 5)), MaybeRelocatable::from(bigint!(1)), MaybeRelocatable::from(bigint_str!(b"48805497317890012913")), ) - )) + ))) ); } @@ -477,13 +480,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 5)), MaybeRelocatable::from(bigint!(55)), MaybeRelocatable::from(bigint!(1)), ) - )) + ))) ); } @@ -531,13 +534,13 @@ mod tests { //Execute the hint assert_eq!( run_hint!(vm, ids_data, hint_code), - Err(VirtualMachineError::MemoryError( + Err(HintError::Internal(VirtualMachineError::MemoryError( MemoryError::InconsistentMemory( MaybeRelocatable::from((1, 10)), MaybeRelocatable::from(bigint!(0)), MaybeRelocatable::from(bigint!(10)), ) - )) + ))) ); } } diff --git a/src/hint_processor/hint_processor_definition.rs b/src/hint_processor/hint_processor_definition.rs index 0c5a921784..4f88b94522 100644 --- a/src/hint_processor/hint_processor_definition.rs +++ b/src/hint_processor/hint_processor_definition.rs @@ -3,6 +3,7 @@ use crate::serde::deserialize_program::OffsetValue; use crate::types::exec_scope::ExecutionScopes; use crate::types::instruction::Register; use crate::vm::errors::hint_errors::HintError; +use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::vm_core::VirtualMachine; use num_bigint::BigInt; use std::any::Any; @@ -36,7 +37,7 @@ pub trait HintProcessor { reference_ids: &HashMap, //List of all references (key corresponds to element of the previous dictionary) references: &HashMap, - ) -> Result, HintError>; + ) -> Result, VirtualMachineError>; } #[derive(Debug, PartialEq, Clone)] diff --git a/src/hint_processor/hint_processor_utils.rs b/src/hint_processor/hint_processor_utils.rs index 84629cf0b9..28cd5f1395 100644 --- a/src/hint_processor/hint_processor_utils.rs +++ b/src/hint_processor/hint_processor_utils.rs @@ -26,7 +26,7 @@ pub fn insert_value_from_reference( ) -> Result<(), HintError> { let var_addr = compute_addr_from_reference(hint_reference, vm, ap_tracking)?; vm.insert_value(&var_addr, value) - .map_err(HintError::InternalError) + .map_err(HintError::Internal) } ///Returns the Integer value stored in the given ids variable @@ -43,7 +43,7 @@ pub fn get_integer_from_reference<'a>( } let var_addr = compute_addr_from_reference(hint_reference, vm, ap_tracking)?; - vm.get_integer(&var_addr).map_err(HintError::InternalError) + vm.get_integer(&var_addr).map_err(HintError::Internal) } ///Returns the Relocatable value stored in the given ids variable @@ -112,7 +112,7 @@ fn apply_ap_tracking_correction( )); } let ap_diff = hint_ap_tracking.offset - ref_ap_tracking.offset; - ap.sub(ap_diff).map_err(HintError::InternalError) + ap.sub(ap_diff).map_err(HintError::Internal) } //Tries to convert a BigInt value to usize diff --git a/src/u.cairo b/src/u.cairo deleted file mode 100644 index e08a84bd9a..0000000000 --- a/src/u.cairo +++ /dev/null @@ -1,23 +0,0 @@ -func assert_not_zero(value: felt){ - %{ - print("test") - a = 1 + 1 - print(a) - %} - if (value == 0) { - value = 1; - } - - return (); -} - -func main() { - assert_not_zero(1); - assert_not_zero(-1); - let x = 500 * 5; - assert_not_zero(x); - tempvar y = -80; - assert_not_zero(y); - - return (); -} \ No newline at end of file diff --git a/src/vm/errors/hint_errors.rs b/src/vm/errors/hint_errors.rs index d56abec7b6..8e9e246471 100644 --- a/src/vm/errors/hint_errors.rs +++ b/src/vm/errors/hint_errors.rs @@ -7,6 +7,8 @@ use super::{exec_scope_errors::ExecScopeError, vm_errors::VirtualMachineError}; #[derive(Debug, PartialEq, Error)] pub enum HintError { + #[error("HintProcessor failed retrieve the compiled data necessary for hint execution")] + WrongHintData, #[error("Failed to get ids for hint execution")] FailedToGetIds, #[error("Tried to compute an address but there was no register in the reference.")] @@ -74,7 +76,7 @@ pub enum HintError { #[error("squash_dict fail: n_accesses: {0} is too big to be converted into an iterator")] NAccessesTooBig(BigInt), #[error(transparent)] - InternalError(#[from] VirtualMachineError), + Internal(#[from] VirtualMachineError), #[error("Couldn't convert BigInt to usize")] BigintToUsizeFail, #[error("usort() can only be used with input_len<={0}. Got: input_len={1}.")] @@ -117,4 +119,24 @@ pub enum HintError { SplitIntNotZero, #[error("split_int(): Limb {0} is out of range.")] SplitIntLimbOutOfRange(BigInt), + #[error("Expected size to be in the range from [0, 100), got: {0}")] + InvalidKeccakStateSizeFelts(BigInt), + #[error("Expected size to be in range from [0, 10), got: {0}")] + InvalidBlockSize(BigInt), + #[error("Couldn't convert BigInt to u32")] + BigintToU32Fail, + #[error("Value of of range {0}")] + ValueOutOfRange(BigInt), + #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")] + AssertNNValueOutOfRange(BigInt), + #[error("Assertion failed, {0} % {1} is equal to 0")] + AssertNotZero(BigInt, BigInt), + #[error("Div out of range: 0 < {0} <= {1}")] + OutOfValidRange(BigInt, BigInt), + #[error("Value: {0} is outside valid range")] + ValueOutsideValidRange(BigInt), + #[error("Assertion failed, {0}, is not less or equal to {1}")] + NonLeFelt(BigInt, BigInt), + #[error("Unknown Hint: {0}")] + UnknownHint(String), } diff --git a/src/vm/errors/vm_errors.rs b/src/vm/errors/vm_errors.rs index dc5141d463..90ea9cebbd 100644 --- a/src/vm/errors/vm_errors.rs +++ b/src/vm/errors/vm_errors.rs @@ -71,22 +71,12 @@ pub enum VirtualMachineError { ExpectedInteger(MaybeRelocatable), #[error("Expected relocatable at address {0}")] ExpectedRelocatable(MaybeRelocatable), - #[error("Assertion failed, {0}, is not less or equal to {1}")] - NonLeFelt(BigInt, BigInt), - #[error("Div out of range: 0 < {0} <= {1}")] - OutOfValidRange(BigInt, BigInt), - #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")] - ValueOutOfRange(BigInt), #[error("Value: {0} should be positive")] ValueNotPositive(BigInt), - #[error("Unknown Hint: {0}")] - UnknownHint(String), - #[error("Value: {0} is outside valid range")] - ValueOutsideValidRange(BigInt), + #[error("Div out of range: 0 < {0} <= {1}")] + OutOfValidRange(BigInt, BigInt), #[error("Failed to compare {0} and {1}, cant compare a relocatable to an integer value")] DiffTypeComparison(MaybeRelocatable, MaybeRelocatable), - #[error("Assertion failed, {0} % {1} is equal to 0")] - AssertNotZero(BigInt, BigInt), #[error("Failed to compare {0} and {1}, cant compare two relocatable values of different segment indexes")] DiffIndexComp(Relocatable, Relocatable), #[error("Couldn't convert BigInt to usize")] @@ -111,14 +101,8 @@ pub enum VirtualMachineError { FailedToGetSqrt(BigInt), #[error("Expected integer, found: {0:?}")] ExpectedIntAtRange(Option), - #[error("Expected size to be in the range from [0, 100), got: {0}")] - InvalidKeccakStateSizeFelts(BigInt), - #[error("Expected size to be in range from [0, 10), got: {0}")] - InvalidBlockSize(BigInt), #[error("Could not convert slice to array")] SliceToArrayError, - #[error("HintProcessor failed retrieve the compiled data necessary for hint execution")] - WrongHintData, #[error("Failed to compile hint: {0}")] CompileHintFail(String), #[error("op1_addr is Op1Addr.IMM, but no immediate was given")] @@ -139,4 +123,6 @@ pub enum VirtualMachineError { ErrorMessageAttribute(String, Box), #[error("Got an exception while executing a hint: {1}")] Hint(usize, Box), + #[error("Unexpected Failure")] + Unexpected, } From 94aa1f133fb4dcc4f0b546a5a0eac9793a232d39 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 17:00:15 -0300 Subject: [PATCH 50/52] Update custom hint example --- custom_hint_example/Cargo.lock | 72 +++++++++++++++++++-------------- custom_hint_example/src/main.rs | 9 +++-- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/custom_hint_example/Cargo.lock b/custom_hint_example/Cargo.lock index da13d2547c..10a3882182 100644 --- a/custom_hint_example/Cargo.lock +++ b/custom_hint_example/Cargo.lock @@ -79,6 +79,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bigdecimal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "bincode" version = "1.3.3" @@ -134,6 +145,7 @@ dependencies = [ "num-integer", "num-traits", "parse-hyperlinks", + "rand_core", "serde", "serde_bytes", "serde_json", @@ -333,15 +345,6 @@ dependencies = [ "digest 0.9.0", ] -[[package]] -name = "html-escape" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e7479fa1ef38eb49fb6a42c426be515df2d063f06cb8efd3e50af073dbc26c" -dependencies = [ - "utf8-width", -] - [[package]] name = "indexmap" version = "1.9.1" @@ -487,10 +490,7 @@ checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" name = "parse-hyperlinks" version = "0.23.4" dependencies = [ - "html-escape", "nom", - "percent-encoding", - "thiserror", ] [[package]] @@ -499,12 +499,6 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - [[package]] name = "pest" version = "2.3.0" @@ -585,9 +579,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -712,9 +706,9 @@ dependencies = [ [[package]] name = "starknet-crypto" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d5ba05430fcd7c107ad9e4433bb3958722b13d97a44fd07a18dcf0eb6da667" +checksum = "be7d6b2c959fde2a10dbc31d54bdd0307eecb7ef6c05c23a0263e65b57b3e18a" dependencies = [ "crypto-bigint", "hex", @@ -724,21 +718,45 @@ dependencies = [ "num-traits", "rfc6979", "sha2 0.9.9", + "starknet-crypto-codegen", + "starknet-curve", "starknet-ff", "thiserror", "zeroize", ] [[package]] -name = "starknet-ff" +name = "starknet-crypto-codegen" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a80865f37a0dcd198f427356d939f1495144c26ed5123b1418ef33a63f82655" +checksum = "6569d70430f0f6edc41f6820d00acf63356e6308046ca01e57eeac22ad258c47" +dependencies = [ + "starknet-curve", + "starknet-ff", + "syn", +] + +[[package]] +name = "starknet-curve" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84be6079d3060fdbd8b5335574fef3d3783fa2f7ee6474d08ae0c1e4b0a29ba4" +dependencies = [ + "starknet-ff", +] + +[[package]] +name = "starknet-ff" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5874510620214ebeac50915b01d67437d8ca10a6682b1de85b93cd01157b58eb" dependencies = [ "ark-ff", + "bigdecimal", "crypto-bigint", "getrandom", "hex", + "num-bigint", "serde", "thiserror", ] @@ -837,12 +855,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" -[[package]] -name = "utf8-width" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" - [[package]] name = "version_check" version = "0.9.4" diff --git a/custom_hint_example/src/main.rs b/custom_hint_example/src/main.rs index c2da588a1c..8b102d263e 100644 --- a/custom_hint_example/src/main.rs +++ b/custom_hint_example/src/main.rs @@ -6,10 +6,11 @@ use cairo_rs::hint_processor::builtin_hint_processor::hint_utils::get_integer_fr use cairo_rs::hint_processor::hint_processor_definition::HintReference; use cairo_rs::types::exec_scope::ExecutionScopes; use cairo_rs::serde::deserialize_program::ApTracking; -use cairo_rs::vm::{errors::vm_errors::VirtualMachineError, vm_core::VirtualMachine}; +use cairo_rs::vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}; use num_bigint::BigInt; use std::collections::HashMap; use std::path::Path; +use std::rc::Rc; // Create the function that implements the custom hint fn print_a_hint( @@ -18,7 +19,7 @@ fn print_a_hint( ids_data: &HashMap, ap_tracking: &ApTracking, _constants: &HashMap, -) -> Result<(), VirtualMachineError> { +) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; println!("{}", a); Ok(()) @@ -32,7 +33,7 @@ fn main() { let mut hint_processor = BuiltinHintProcessor::new_empty(); //Add the custom hint, together with the Python code - hint_processor.add_hint(String::from("print(ids.a)"), hint); + hint_processor.add_hint(String::from("print(ids.a)"), Rc::new(hint)); //Run the cairo program cairo_run( @@ -40,6 +41,8 @@ fn main() { "main", false, false, + "all", + false, &mut hint_processor, ) .expect("Couldn't run program"); From c683b6d353512464960fd0dacd0201a98488e769 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 17:03:08 -0300 Subject: [PATCH 51/52] Fix changelog format --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3d0a4b937..7d4006d5a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ * Use hint location instead of instruction location when building VmExceptions from hint failure [#673](https://github.com/lambdaclass/cairo-rs/pull/673/files) * Public Api changes: - * `hints` field added to `InstructionLocation` - * `Program.instruction_locations` type changed from `Option>` to `Option>` - * `VirtualMachineError`s produced by `HintProcessor::execute_hint()` will be wrapped in a `VirtualMachineError::Hint` error containing their hint_index - * `get_location()` now receives an an optional usize value `hint_index`, used to obtain hint locations + * `hints` field added to `InstructionLocation` + * `Program.instruction_locations` type changed from `Option>` to `Option>` + * `VirtualMachineError`s produced by `HintProcessor::execute_hint()` will be wrapped in a `VirtualMachineError::Hint` error containing their hint_index + * `get_location()` now receives an an optional usize value `hint_index`, used to obtain hint locations From 31fdb1ef8de6ef31944619a0ff910b50b721dc29 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 29 Dec 2022 17:07:26 -0300 Subject: [PATCH 52/52] Add changelog entry for this PR --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3d0a4b937..180612140d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,3 +17,9 @@ * `Program.instruction_locations` type changed from `Option>` to `Option>` * `VirtualMachineError`s produced by `HintProcessor::execute_hint()` will be wrapped in a `VirtualMachineError::Hint` error containing their hint_index * `get_location()` now receives an an optional usize value `hint_index`, used to obtain hint locations + +* Add new error type `HintError` [#676](https://github.com/lambdaclass/cairo-rs/pull/676) + * Public Api changes: + * `HintProcessor::execute_hint()` now returns a `HintError` instead of a `VirtualMachineError` + * helper functions on `hint_processor_utils.rs` now return a `HintError` +