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 487749c..3cb165d 100644 --- a/src/value.rs +++ b/src/value.rs @@ -175,7 +175,7 @@ impl Value { | StarkNetTypeConcrete::StorageAddress(_) => matches!(self, Self::Felt(_)), StarkNetTypeConcrete::System(_) => matches!(self, Self::Unit), StarkNetTypeConcrete::Secp256Point(_) => todo!(), - StarkNetTypeConcrete::Sha256StateHandle(_) => todo!(), + 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..e4814e1 100644 --- a/src/vm/array.rs +++ b/src/vm/array.rs @@ -29,7 +29,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!(), } } @@ -185,3 +187,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..a9a805b 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,113 @@ 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()), - _ => unreachable!(), - }, - CoreTypeConcrete::Uint8(_) => match inner_data { - [GenericArg::Value(value)] => Value::U8(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::Uint128(_) => match inner_data { - [GenericArg::Value(value)] => Value::U128(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::Struct(_) => { - let mut fields = Vec::new(); + _ => 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()), + _ => 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/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..7ef0779 100644 --- a/src/vm/starknet.rs +++ b/src/vm/starknet.rs @@ -79,9 +79,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) } @@ -925,3 +931,87 @@ 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::>(), + } + ], + ), + } +} diff --git a/src/vm/uint128.rs b/src/vm/uint128.rs index e3876ec..09e902b 100644 --- a/src/vm/uint128.rs +++ b/src/vm/uint128.rs @@ -214,3 +214,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)]) +}