diff --git a/src/test_utils.rs b/src/test_utils.rs index 672ccec..03d70b6 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -1,3 +1,5 @@ +#![cfg(test)] + use std::{fs, path::Path, sync::Arc}; use cairo_lang_compiler::{ diff --git a/src/value.rs b/src/value.rs index b0fbb32..d2940d7 100644 --- a/src/value.rs +++ b/src/value.rs @@ -62,6 +62,7 @@ pub enum Value { U32(u32), U64(u64), U8(u8), + Null, Uninitialized { ty: ConcreteTypeId, }, @@ -80,6 +81,7 @@ impl Value { CoreTypeConcrete::Uint16(_) => Value::U16(0), CoreTypeConcrete::Uint128(_) => Value::U128(0), CoreTypeConcrete::Felt252(_) => Value::Felt(0.into()), + CoreTypeConcrete::Nullable(_) => Value::Null, x => panic!("type {:?} has no default value implementation", x.info()), } } @@ -106,7 +108,9 @@ impl Value { matches!(self, Self::FeltDict { ty, .. } if *ty == info.ty) } CoreTypeConcrete::GasBuiltin(_) => matches!(self, Self::U128(_)), - CoreTypeConcrete::NonZero(info) => self.is(registry, &info.ty), + CoreTypeConcrete::NonZero(info) => { + self.is(registry, &info.ty) + } CoreTypeConcrete::Sint128(_) => matches!(self, Self::I128(_)), CoreTypeConcrete::Sint32(_) => matches!(self, Self::I32(_)), CoreTypeConcrete::Sint8(_) => matches!(self, Self::I8(_)), @@ -172,8 +176,8 @@ impl Value { | StarkNetTypeConcrete::StorageBaseAddress(_) | StarkNetTypeConcrete::StorageAddress(_) => matches!(self, Self::Felt(_)), StarkNetTypeConcrete::System(_) => matches!(self, Self::Unit), - StarkNetTypeConcrete::Secp256Point(_) => todo!(), - StarkNetTypeConcrete::Sha256StateHandle(_) => todo!(), + StarkNetTypeConcrete::Secp256Point(_) => matches!(self, Self::Struct { .. }), + StarkNetTypeConcrete::Sha256StateHandle(_) => matches!(self, Self::Struct { .. }), }, }; diff --git a/src/vm.rs b/src/vm.rs index 507b124..bede656 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -7,6 +7,7 @@ use crate::{ use cairo_lang_sierra::{ edit_state, extensions::{ + circuit::CircuitTypeConcrete, core::{CoreConcreteLibfunc, CoreLibfunc, CoreType, CoreTypeConcrete}, starknet::StarkNetTypeConcrete, ConcreteType, @@ -137,6 +138,10 @@ impl VirtualMachine { } CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::System(_)) => Value::Unit, CoreTypeConcrete::RangeCheck(_) + | CoreTypeConcrete::RangeCheck96(_) + | CoreTypeConcrete::Circuit( + CircuitTypeConcrete::MulMod(_) | CircuitTypeConcrete::AddMod(_), + ) | CoreTypeConcrete::Pedersen(_) | CoreTypeConcrete::Poseidon(_) | CoreTypeConcrete::Bitwise(_) diff --git a/src/vm/array.rs b/src/vm/array.rs index fbee0f2..dd0ccde 100644 --- a/src/vm/array.rs +++ b/src/vm/array.rs @@ -5,6 +5,7 @@ use cairo_lang_sierra::{ array::ArrayConcreteLibfunc, core::{CoreLibfunc, CoreType, CoreTypeConcrete}, lib_func::{SignatureAndTypeConcreteLibfunc, SignatureOnlyConcreteLibfunc}, + ConcreteLibfunc, }, program_registry::ProgramRegistry, }; @@ -17,7 +18,7 @@ pub fn eval( ) -> EvalAction { match selector { ArrayConcreteLibfunc::New(info) => eval_new(registry, info, args), - ArrayConcreteLibfunc::SpanFromTuple(_) => todo!(), + ArrayConcreteLibfunc::SpanFromTuple(info) => eval_span_from_tuple(registry, info, args), ArrayConcreteLibfunc::TupleFromSpan(_) => todo!(), ArrayConcreteLibfunc::Append(info) => eval_append(registry, info, args), ArrayConcreteLibfunc::PopFront(info) => eval_pop_front(registry, info, args), @@ -29,7 +30,9 @@ pub fn eval( eval_snapshot_pop_front(registry, info, args) } ArrayConcreteLibfunc::SnapshotPopBack(info) => eval_snapshot_pop_back(registry, info, args), - ArrayConcreteLibfunc::SnapshotMultiPopFront(_) => todo!(), + ArrayConcreteLibfunc::SnapshotMultiPopFront(info) => { + eval_snapshot_multi_pop_front(registry, info, args) + } ArrayConcreteLibfunc::SnapshotMultiPopBack(_) => todo!(), } } @@ -48,7 +51,7 @@ pub fn eval_new( CoreTypeConcrete::Array(info) => &info.ty, _ => unreachable!(), }; - + //dbg!("ARRAY: {}", &ty); EvalAction::NormalBranch( 0, smallvec![Value::Array { @@ -58,6 +61,38 @@ pub fn eval_new( ) } +fn eval_span_from_tuple( + registry: &ProgramRegistry, + info: &SignatureAndTypeConcreteLibfunc, + args: Vec, +) -> EvalAction { + let [Value::Struct(data)]: [Value; 1] = args.try_into().unwrap() else { + panic!() + }; + + let type_info = registry + .get_type(&info.branch_signatures()[0].vars[0].ty) + .unwrap(); + let ty = match type_info { + CoreTypeConcrete::Snapshot(info) => { + let type_info = registry.get_type(&info.ty).unwrap(); + match type_info { + CoreTypeConcrete::Array(info) => &info.ty, + _ => unreachable!(), + } + } + _ => unreachable!(), + }; + + EvalAction::NormalBranch( + 0, + smallvec![Value::Array { + ty: ty.clone(), + data + }], + ) +} + pub fn eval_append( registry: &ProgramRegistry, info: &SignatureAndTypeConcreteLibfunc, @@ -185,3 +220,29 @@ pub fn eval_snapshot_pop_back( EvalAction::NormalBranch(1, smallvec![Value::Array { data, ty }]) } } + +fn eval_snapshot_multi_pop_front( + registry: &ProgramRegistry, + info: &cairo_lang_sierra::extensions::array::ConcreteMultiPopLibfunc, + args: Vec, +) -> EvalAction { + let [rangecheck, Value::Array { mut data, ty }]: [Value; 2] = args.try_into().unwrap() else { + panic!() + }; + + let CoreTypeConcrete::Struct(popped_cty) = registry.get_type(&info.popped_ty).unwrap() else { + panic!() + }; + + if data.len() >= popped_cty.members.len() { + let new_data = data.split_off(popped_cty.members.len()); + let value = Value::Struct(data); + assert!(value.is(registry, &info.popped_ty)); + EvalAction::NormalBranch( + 0, + smallvec![rangecheck, Value::Array { data: new_data, ty }, value], + ) + } else { + EvalAction::NormalBranch(1, smallvec![rangecheck, Value::Array { data, ty }]) + } +} diff --git a/src/vm/cast.rs b/src/vm/cast.rs index 30a1d03..10aaacf 100644 --- a/src/vm/cast.rs +++ b/src/vm/cast.rs @@ -97,6 +97,10 @@ pub fn eval_upcast( CoreTypeConcrete::Uint32(_) => Value::U32(value.try_into().unwrap()), CoreTypeConcrete::Uint64(_) => Value::U64(value.try_into().unwrap()), CoreTypeConcrete::Uint128(_) => Value::U128(value.try_into().unwrap()), + CoreTypeConcrete::Felt252(_) => Value::Felt(value.try_into().unwrap()), + CoreTypeConcrete::Sint16(_) => todo!("Sint16"), + CoreTypeConcrete::Sint64(_) => todo!("Sint64"), + CoreTypeConcrete::BoundedInt(_) => todo!("BoundedInt"), _ => todo!(), }], ) diff --git a/src/vm/const.rs b/src/vm/const.rs index 66ad442..d6269d3 100644 --- a/src/vm/const.rs +++ b/src/vm/const.rs @@ -2,7 +2,9 @@ use super::EvalAction; use crate::Value; use cairo_lang_sierra::{ extensions::{ - const_type::{ConstAsImmediateConcreteLibfunc, ConstConcreteLibfunc}, + const_type::{ + ConstAsBoxConcreteLibfunc, ConstAsImmediateConcreteLibfunc, ConstConcreteLibfunc, + }, core::{CoreLibfunc, CoreType, CoreTypeConcrete}, }, ids::ConcreteTypeId, @@ -17,7 +19,7 @@ pub fn eval( args: Vec, ) -> EvalAction { match selector { - ConstConcreteLibfunc::AsBox(_) => todo!(), + ConstConcreteLibfunc::AsBox(info) => eval_as_box(registry, info, args), ConstConcreteLibfunc::AsImmediate(info) => eval_as_immediate(registry, info, args), } } @@ -29,94 +31,117 @@ pub fn eval_as_immediate( ) -> EvalAction { let [] = args.try_into().unwrap(); - fn inner( - registry: &ProgramRegistry, - type_id: &ConcreteTypeId, - inner_data: &[GenericArg], - ) -> Value { - match registry.get_type(type_id).unwrap() { - CoreTypeConcrete::BoundedInt(info) => match inner_data { - [GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() { - CoreTypeConcrete::Const(info) => { - inner(registry, &info.inner_ty, &info.inner_data) - } - _ => unreachable!(), - }, - [GenericArg::Value(value)] => { - assert!(value >= &info.range.lower && value < &info.range.upper); - Value::BoundedInt { - range: info.range.lower.clone()..info.range.upper.clone(), - value: value.clone(), - } - } - _ => unreachable!(), - }, - CoreTypeConcrete::Felt252(_) => match inner_data { - [GenericArg::Value(value)] => Value::Felt(value.into()), - _ => unreachable!(), - }, - CoreTypeConcrete::NonZero(info) => inner(registry, &info.ty, inner_data), - CoreTypeConcrete::Sint128(_) => match inner_data { - [GenericArg::Value(value)] => Value::I128(value.try_into().unwrap()), - _ => unreachable!(), - }, - CoreTypeConcrete::Sint32(_) => match inner_data { - [GenericArg::Value(value)] => Value::I32(value.try_into().unwrap()), - _ => unreachable!(), - }, - CoreTypeConcrete::Sint8(_) => match inner_data { - [GenericArg::Value(value)] => Value::I8(value.try_into().unwrap()), - _ => unreachable!(), - }, - CoreTypeConcrete::Uint64(_) => match inner_data { - [GenericArg::Value(value)] => Value::U64(value.try_into().unwrap()), - _ => unreachable!(), - }, - CoreTypeConcrete::Uint32(_) => match inner_data { - [GenericArg::Value(value)] => Value::U32(value.try_into().unwrap()), + let const_ty = match registry.get_type(&info.const_type).unwrap() { + CoreTypeConcrete::Const(x) => x, + _ => unreachable!(), + }; + EvalAction::NormalBranch( + 0, + smallvec![inner(registry, &const_ty.inner_ty, &const_ty.inner_data)], + ) +} + +pub fn eval_as_box( + registry: &ProgramRegistry, + info: &ConstAsBoxConcreteLibfunc, + args: Vec, +) -> EvalAction { + let [] = args.try_into().unwrap(); + + let const_ty = match registry.get_type(&info.const_type).unwrap() { + CoreTypeConcrete::Const(x) => x, + _ => unreachable!(), + }; + EvalAction::NormalBranch( + 0, + smallvec![inner(registry, &const_ty.inner_ty, &const_ty.inner_data)], + ) +} + +fn inner( + registry: &ProgramRegistry, + type_id: &ConcreteTypeId, + inner_data: &[GenericArg], +) -> Value { + match registry.get_type(type_id).unwrap() { + CoreTypeConcrete::BoundedInt(info) => match inner_data { + [GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() { + CoreTypeConcrete::Const(info) => inner(registry, &info.inner_ty, &info.inner_data), _ => unreachable!(), }, - CoreTypeConcrete::Uint8(_) => match inner_data { - [GenericArg::Value(value)] => Value::U8(value.try_into().unwrap()), + [GenericArg::Value(value)] => { + assert!(value >= &info.range.lower && value < &info.range.upper); + Value::BoundedInt { + range: info.range.lower.clone()..info.range.upper.clone(), + value: value.clone(), + } + } + _ => unreachable!(), + }, + CoreTypeConcrete::Felt252(_) => match inner_data { + [GenericArg::Value(value)] => Value::Felt(value.into()), + _ => unreachable!(), + }, + CoreTypeConcrete::NonZero(info) => inner(registry, &info.ty, inner_data), + CoreTypeConcrete::Sint128(_) => match inner_data { + [GenericArg::Value(value)] => Value::I128(value.try_into().unwrap()), + _ => unreachable!(), + }, + CoreTypeConcrete::Sint32(_) => match inner_data { + [GenericArg::Value(value)] => Value::I32(value.try_into().unwrap()), + _ => unreachable!(), + }, + CoreTypeConcrete::Sint8(_) => match inner_data { + [GenericArg::Value(value)] => Value::I8(value.try_into().unwrap()), + _ => unreachable!(), + }, + CoreTypeConcrete::Uint64(_) => match inner_data { + [GenericArg::Value(value)] => Value::U64(value.try_into().unwrap()), + _ => unreachable!(), + }, + CoreTypeConcrete::Uint32(_) => match inner_data { + [GenericArg::Value(value)] => Value::U32(value.try_into().unwrap()), + [GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() { + CoreTypeConcrete::Const(info) => inner(registry, &info.inner_ty, &info.inner_data), _ => unreachable!(), }, - CoreTypeConcrete::Uint128(_) => match inner_data { - [GenericArg::Value(value)] => Value::U128(value.try_into().unwrap()), + _ => unreachable!(), + }, + CoreTypeConcrete::Uint8(_) => match inner_data { + [GenericArg::Value(value)] => Value::U8(value.try_into().unwrap()), + _ => unreachable!(), + }, + CoreTypeConcrete::Uint128(_) => match inner_data { + [GenericArg::Value(value)] => Value::U128(value.try_into().unwrap()), + [GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() { + CoreTypeConcrete::Const(info) => inner(registry, &info.inner_ty, &info.inner_data), _ => unreachable!(), }, - CoreTypeConcrete::Struct(_) => { - let mut fields = Vec::new(); + _ => unreachable!(), + }, + CoreTypeConcrete::Struct(_) => { + let mut fields = Vec::new(); - for field in inner_data { - match field { - GenericArg::Type(const_field_ty) => { - let field_type = registry.get_type(const_field_ty).unwrap(); + for field in inner_data { + match field { + GenericArg::Type(const_field_ty) => { + let field_type = registry.get_type(const_field_ty).unwrap(); - match &field_type { - CoreTypeConcrete::Const(const_ty) => { - let field_value = - inner(registry, &const_ty.inner_ty, &const_ty.inner_data); - fields.push(field_value); - } - _ => unreachable!(), - }; - } - _ => unreachable!(), + match &field_type { + CoreTypeConcrete::Const(const_ty) => { + let field_value = + inner(registry, &const_ty.inner_ty, &const_ty.inner_data); + fields.push(field_value); + } + _ => unreachable!(), + }; } + _ => unreachable!(), } - - Value::Struct(fields) } - _ => todo!("{}", type_id), + + Value::Struct(fields) } + _ => todo!("{}", type_id), } - - let const_ty = match registry.get_type(&info.const_type).unwrap() { - CoreTypeConcrete::Const(x) => x, - _ => unreachable!(), - }; - EvalAction::NormalBranch( - 0, - smallvec![inner(registry, &const_ty.inner_ty, &const_ty.inner_data)], - ) } diff --git a/src/vm/function_call.rs b/src/vm/function_call.rs index 3b72985..a3fa7c1 100644 --- a/src/vm/function_call.rs +++ b/src/vm/function_call.rs @@ -17,7 +17,7 @@ pub fn eval( assert!(args .iter() .zip(&info.function.params) - .all(|(value, param)| value.is(registry, ¶m.ty))); + .all(|(value, param)| { value.is(registry, ¶m.ty) })); EvalAction::FunctionCall(info.function.id.clone(), args.into_iter().collect()) } diff --git a/src/vm/int128.rs b/src/vm/int128.rs index e1cfd1a..8c489fe 100644 --- a/src/vm/int128.rs +++ b/src/vm/int128.rs @@ -1,5 +1,3 @@ -use std::u128; - use cairo_lang_sierra::{ extensions::{ core::{CoreLibfunc, CoreType}, @@ -22,12 +20,12 @@ pub fn eval( args: Vec, ) -> EvalAction { match selector { - Sint128Concrete::Const(info) => todo!("1"), + Sint128Concrete::Const(_) => todo!("int128 const"), Sint128Concrete::Operation(info) => eval_operation(registry, info, args), Sint128Concrete::Equal(info) => eval_equal(registry, info, args), Sint128Concrete::ToFelt252(info) => eval_to_felt(registry, info, args), Sint128Concrete::FromFelt252(info) => eval_from_felt(registry, info, args), - Sint128Concrete::IsZero(info) => todo!("6"), + Sint128Concrete::IsZero(_) => todo!("int128 is_zero"), Sint128Concrete::Diff(info) => eval_diff(registry, info, args), } } diff --git a/src/vm/starknet.rs b/src/vm/starknet.rs index fa1401b..79c7c87 100644 --- a/src/vm/starknet.rs +++ b/src/vm/starknet.rs @@ -1,11 +1,14 @@ use super::EvalAction; -use crate::{starknet::StarknetSyscallHandler, Value}; +use crate::{ + starknet::{StarknetSyscallHandler, U256}, + Value, +}; use cairo_lang_sierra::{ extensions::{ consts::SignatureAndConstConcreteLibfunc, core::{CoreLibfunc, CoreType, CoreTypeConcrete}, lib_func::SignatureOnlyConcreteLibfunc, - starknet::StarkNetConcreteLibfunc, + starknet::{secp256::Secp256ConcreteLibfunc, StarkNetConcreteLibfunc}, ConcreteLibfunc, }, program_registry::ProgramRegistry, @@ -79,9 +82,15 @@ pub fn eval( } StarkNetConcreteLibfunc::Deploy(info) => eval_deploy(registry, info, args, syscall_handler), StarkNetConcreteLibfunc::Keccak(info) => eval_keccak(registry, info, args, syscall_handler), - StarkNetConcreteLibfunc::Sha256ProcessBlock(_) => todo!(), - StarkNetConcreteLibfunc::Sha256StateHandleInit(_) => todo!(), - StarkNetConcreteLibfunc::Sha256StateHandleDigest(_) => todo!(), + StarkNetConcreteLibfunc::Sha256ProcessBlock(info) => { + eval_sha256_process_block(registry, info, args, syscall_handler) + } + StarkNetConcreteLibfunc::Sha256StateHandleInit(info) => { + eval_sha256_state_handle_init(registry, info, args, syscall_handler) + } + StarkNetConcreteLibfunc::Sha256StateHandleDigest(info) => { + eval_sha256_state_handle_digest(registry, info, args, syscall_handler) + } StarkNetConcreteLibfunc::LibraryCall(info) => { eval_library_call(registry, info, args, syscall_handler) } @@ -92,7 +101,9 @@ pub fn eval( eval_send_message_to_l1(registry, info, args, syscall_handler) } StarkNetConcreteLibfunc::Testing(_info) => todo!(), - StarkNetConcreteLibfunc::Secp256(_info) => todo!(), + StarkNetConcreteLibfunc::Secp256(info) => { + eval_secp256(registry, info, args, syscall_handler) + } } } @@ -925,3 +936,314 @@ fn eval_send_message_to_l1( ), } } + +fn eval_sha256_state_handle_init( + _registry: &ProgramRegistry, + _info: &SignatureOnlyConcreteLibfunc, + args: Vec, + _syscall_handler: &mut impl StarknetSyscallHandler, +) -> EvalAction { + let [value]: [Value; 1] = args.try_into().unwrap(); + + EvalAction::NormalBranch(0, smallvec![value]) +} + +fn eval_sha256_state_handle_digest( + _registry: &ProgramRegistry, + _info: &SignatureOnlyConcreteLibfunc, + args: Vec, + _syscall_handler: &mut impl StarknetSyscallHandler, +) -> EvalAction { + let [value]: [Value; 1] = args.try_into().unwrap(); + + EvalAction::NormalBranch(0, smallvec![value]) +} + +fn eval_sha256_process_block( + registry: &ProgramRegistry, + info: &SignatureOnlyConcreteLibfunc, + args: Vec, + syscall_handler: &mut impl StarknetSyscallHandler, +) -> EvalAction { + let [Value::U128(mut gas), system, Value::Struct(prev_state), Value::Struct(current_block)]: [Value; 4] = args.try_into().unwrap() else { + panic!() + }; + + let prev_state: [u32; 8] = prev_state + .into_iter() + .map(|v| { + let Value::U32(v) = v else { panic!() }; + v + }) + .collect::>() + .try_into() + .unwrap(); + let current_block: [u32; 16] = current_block + .into_iter() + .map(|v| { + let Value::U32(v) = v else { panic!() }; + v + }) + .collect::>() + .try_into() + .unwrap(); + + // get felt type from the error branch array + let felt_ty = { + match registry + .get_type(&info.branch_signatures()[1].vars[2].ty) + .unwrap() + { + CoreTypeConcrete::Array(info) => info.ty.clone(), + _ => unreachable!(), + } + }; + + match syscall_handler.sha256_process_block(prev_state, current_block, &mut gas) { + Ok(payload) => { + let payload = payload.into_iter().map(Value::U32).collect::>(); + EvalAction::NormalBranch( + 0, + smallvec![Value::U128(gas), system, Value::Struct(payload)], + ) + } + Err(payload) => EvalAction::NormalBranch( + 1, + smallvec![ + Value::U128(gas), + system, + Value::Array { + ty: felt_ty, + data: payload.into_iter().map(Value::Felt).collect::>(), + } + ], + ), + } +} + +fn eval_secp256( + registry: &ProgramRegistry, + info: &Secp256ConcreteLibfunc, + args: Vec, + syscall_handler: &mut impl StarknetSyscallHandler, +) -> EvalAction { + match info { + Secp256ConcreteLibfunc::K1(libfunc) => match libfunc { + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::New(_) => todo!(), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::Add(_) => todo!(), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::Mul(_) => todo!(), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::GetPointFromX(_) => todo!(), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::GetXy(_) => todo!(), + }, + Secp256ConcreteLibfunc::R1(libfunc) => match libfunc { + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::New(info) => eval_secp256r1_new(registry, info, args, syscall_handler), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::Add(_) => todo!(), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::Mul(_) => todo!(), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::GetPointFromX(info) => eval_secp256r1_get_point_from_x(registry, info, args, syscall_handler), + cairo_lang_sierra::extensions::starknet::secp256::Secp256OpConcreteLibfunc::GetXy(_) => todo!(), + }, + } +} + +// Secp256R1 libfuncs evaluations + +fn eval_secp256r1_new( + registry: &ProgramRegistry, + info: &SignatureOnlyConcreteLibfunc, + args: Vec, + syscall_handler: &mut impl StarknetSyscallHandler, +) -> EvalAction { + // dbg!( + // "SIGNATURE: {}", + // info.signature + // .param_signatures + // .iter() + // .map(|x| &x.ty) + // .collect::>() + // ); + // dbg!( + // "SIGNATURE: {}", + // info.signature + // .branch_signatures + // .iter() + // .map(|x| x.vars.iter().map(|x| &x.ty).collect::>()) + // .collect::>() + // ); + // dbg!("ARGS {}", &args); + + let [Value::U128(mut gas), system, Value::Struct(x), Value::Struct(y)]: [Value; 4] = + args.try_into().unwrap() + else { + panic!() + }; + + let [Value::U128(lo_x), Value::U128(hi_x)]: [Value; 2] = x.to_owned().try_into().unwrap() + else { + panic!(); + }; + let [Value::U128(lo_y), Value::U128(hi_y)]: [Value; 2] = y.to_owned().try_into().unwrap() + else { + panic!(); + }; + + let x_u256 = U256 { lo: lo_x, hi: hi_x }; + let y_u256 = U256 { lo: lo_y, hi: hi_y }; + + match syscall_handler.secp256r1_new(x_u256, y_u256, &mut gas) { + Ok(payload) => { + let payload_ty = info.branch_signatures()[0].vars[2].ty.clone(); + + match payload { + Some(p) => { + let payload = Box::new(p.into_value()); + EvalAction::NormalBranch( + 0, + smallvec![ + Value::U128(gas), + system, + Value::Enum { + self_ty: payload_ty, + index: 0, + payload + } + ], + ) + } + None => { + let payload = Box::new(Value::Struct(vec![ + Value::Struct(vec![Value::U128(0), Value::U128(0)]), + Value::Struct(vec![Value::U128(0), Value::U128(0)]), + ])); + EvalAction::NormalBranch( + 0, + smallvec![ + Value::U128(gas), + system, + Value::Enum { + self_ty: payload_ty, + index: 1, + payload + }, + ], + ) + } + } + } + Err(payload) => { + dbg!("ERR"); + let felt_ty = { + match registry + .get_type(&info.branch_signatures()[1].vars[2].ty) + .unwrap() + { + CoreTypeConcrete::Array(info) => info.ty.clone(), + _ => unreachable!(), + } + }; + + EvalAction::NormalBranch( + 1, + smallvec![ + Value::U128(gas), + system, + Value::Array { + ty: felt_ty, + data: payload.into_iter().map(Value::Felt).collect::>() + } + ], + ) + } + } +} + +fn eval_secp256r1_get_point_from_x( + registry: &ProgramRegistry, + info: &SignatureOnlyConcreteLibfunc, + args: Vec, + syscall_handler: &mut impl StarknetSyscallHandler, +) -> EvalAction { + // dbg!("SIGNATURE: {}", info.signature.param_signatures.iter().map(|x| &x.ty).collect::>()); + // dbg!("SIGNATURE: {}", info.signature.branch_signatures.iter().map(|x| x.vars.iter().map(|x|&x.ty).collect::>()).collect::>()); + // dbg!("ARGS {}", &args); + let [Value::U128(mut gas), system, Value::Struct(x_arg), Value::Enum { + self_ty: _, + index, + payload: _, + }]: [Value; 4] = args.try_into().unwrap() + else { + panic!() + }; + + let [Value::U128(lo), Value::U128(hi)]: [Value; 2] = x_arg[..].to_owned().try_into().unwrap() + else { + panic!(); + }; + + let x = U256 { lo, hi }; + let y_parity = index == 0; + + match syscall_handler.secp256r1_get_point_from_x(x, y_parity, &mut gas) { + Ok(payload) => { + let payload_ty = info.branch_signatures()[0].vars[2].ty.clone(); + match payload { + Some(p) => { + let payload = Box::new(p.into_value()); + dbg!(&payload); + EvalAction::NormalBranch( + 0, + smallvec![ + Value::U128(gas), + system, + Value::Enum { + self_ty: payload_ty, + index: 0, + payload + } + ], + ) + } + None => { + let payload = Box::new(Value::Struct(vec![ + Value::Struct(vec![Value::U128(0), Value::U128(0)]), + Value::Struct(vec![Value::U128(0), Value::U128(0)]), + ])); + EvalAction::NormalBranch( + 0, + smallvec![ + Value::U128(gas), + system, + Value::Enum { + self_ty: payload_ty, + index: 1, + payload + }, + ], + ) + } + } + } + Err(payload) => { + let felt_ty = { + match registry + .get_type(&info.branch_signatures()[1].vars[2].ty) + .unwrap() + { + CoreTypeConcrete::Array(info) => info.ty.clone(), + _ => unreachable!(), + } + }; + + EvalAction::NormalBranch( + 1, + smallvec![ + Value::U128(gas), + system, + Value::Array { + ty: felt_ty, + data: payload.into_iter().map(Value::Felt).collect::>() + } + ], + ) + } + } +} diff --git a/src/vm/uint128.rs b/src/vm/uint128.rs index d36e932..7dc4c83 100644 --- a/src/vm/uint128.rs +++ b/src/vm/uint128.rs @@ -33,7 +33,7 @@ pub fn eval( Uint128Concrete::Bitwise(info) => eval_bitwise(registry, info, args), Uint128Concrete::GuaranteeMul(info) => eval_guarantee_mul(registry, info, args), Uint128Concrete::MulGuaranteeVerify(info) => eval_guarantee_verify(registry, info, args), - Uint128Concrete::ByteReverse(_) => todo!(), + Uint128Concrete::ByteReverse(info) => eval_byte_reverse(registry, info, args), } } @@ -201,3 +201,17 @@ pub fn eval_from_felt( ) } } + +pub fn eval_byte_reverse( + _registry: &ProgramRegistry, + _info: &SignatureOnlyConcreteLibfunc, + args: Vec, +) -> EvalAction { + let [bitwise @ Value::Unit, Value::U128(value)]: [Value; 2] = args.try_into().unwrap() else { + panic!() + }; + + let value = value.swap_bytes(); + + EvalAction::NormalBranch(0, smallvec![bitwise, Value::U128(value)]) +} diff --git a/src/vm/uint252.rs b/src/vm/uint252.rs index d57682e..bdc7e91 100644 --- a/src/vm/uint252.rs +++ b/src/vm/uint252.rs @@ -20,7 +20,7 @@ pub fn eval( Uint256Concrete::IsZero(info) => eval_is_zero(registry, info, args), Uint256Concrete::Divmod(info) => eval_divmod(registry, info, args), Uint256Concrete::SquareRoot(_) => todo!(), - Uint256Concrete::InvModN(_) => todo!(), + Uint256Concrete::InvModN(info) => eval_inv_mod_n(registry, info, args), } } @@ -107,3 +107,69 @@ pub fn eval_divmod( ], ) } + +pub fn eval_inv_mod_n( + _registry: &ProgramRegistry, + info: &SignatureOnlyConcreteLibfunc, + args: Vec, +) -> EvalAction { + // dbg!( + // "SIGNATURE: {}", + // info.signature + // .param_signatures + // .iter() + // .map(|x| &x.ty) + // .collect::>() + // ); + // dbg!( + // "BRANCH: {}", + // info.signature + // .branch_signatures + // .iter() + // .map(|x| x.vars.iter().map(|x| &x.ty).collect::>()) + // .collect::>() + // ); + let [range_check @ Value::Unit, Value::Struct(fields), Value::Struct(modulus_struct)]: [Value; + 3] = args.try_into().unwrap() + else { + panic!() + }; + + let [Value::U128(fields_lo), Value::U128(fields_hi)]: [Value; 2] = + fields.clone().try_into().unwrap() + else { + panic!() + }; + + let [Value::Struct(modulus)]: [Value; 1] = modulus_struct.try_into().unwrap() else { + panic!() + }; + + let [Value::U128(mod_lo), Value::U128(mod_hi)]: [Value; 2] = + modulus.clone().try_into().unwrap() + else { + panic!() + }; + + let num = u256_to_biguint(fields_lo, fields_hi); + let modulus = u256_to_biguint(mod_lo, mod_hi); + + match num.modinv(&modulus) { + Some(r) => EvalAction::NormalBranch( + 0, + smallvec![ + range_check, + u256_to_value(r), + Value::Unit, + Value::Unit, + Value::Unit, + Value::Unit, + Value::Unit, + Value::Unit, + Value::Unit, + Value::Unit + ], + ), + None => EvalAction::NormalBranch(1, smallvec![range_check, Value::Unit, Value::Unit]), + } +}