Skip to content

Commit

Permalink
Merge pull request #108 from HerodotusDev/hints/rlp
Browse files Browse the repository at this point in the history
  • Loading branch information
codyx authored Dec 2, 2024
2 parents 5146915 + 17adde9 commit 697ac49
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 14 deletions.
5 changes: 5 additions & 0 deletions cairo_vm_hints/src/hint_processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ impl CustomHintProcessor {
hints.insert(lib::decoder::evm::has_type_prefix::HINT_HAS_TYPE_PREFIX.into(), lib::decoder::evm::has_type_prefix::hint_has_type_prefix);
hints.insert(lib::decoder::evm::is_byzantium::HINT_IS_BYZANTIUM.into(), lib::decoder::evm::is_byzantium::hint_is_byzantium);
hints.insert(lib::decoder::evm::v_is_encoded::HINT_V_IS_ENCODED.into(), lib::decoder::evm::v_is_encoded::hint_v_is_encoded);
hints.insert(lib::rlp::divmod::HINT_DIVMOD_RLP.into(), lib::rlp::divmod::hint_divmod_rlp);
hints.insert(lib::rlp::divmod::HINT_DIVMOD_VALUE.into(), lib::rlp::divmod::hint_divmod_value);
hints.insert(lib::rlp::item_type::HINT_IS_LONG.into(), lib::rlp::item_type::hint_is_long);
hints.insert(lib::rlp::item_type::HINT_ITEM_TYPE.into(), lib::rlp::item_type::hint_item_type);
hints.insert(lib::rlp::processed_words::HINT_PROCESSED_WORDS.into(), lib::rlp::processed_words::hint_processed_words);
hints.insert(lib::print::PROGRAM_HASH.into(), lib::print::program_hash);
hints.insert(lib::segments::SEGMENTS_ADD.into(), lib::segments::segments_add);
hints.insert(lib::segments::SEGMENTS_ADD_EVM_MEMORIZER_SEGMENT_INDEX.into(), lib::segments::segments_add_evm_memorizer_segment_index);
Expand Down
1 change: 1 addition & 0 deletions cairo_vm_hints/src/hints/lib/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod contract_bootloader;
pub mod decoder;
pub mod print;
pub mod rlp;
pub mod segments;
122 changes: 122 additions & 0 deletions cairo_vm_hints/src/hints/lib/rlp/divmod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use cairo_vm::{
hint_processor::builtin_hint_processor::{
builtin_hint_processor_definition::HintProcessorData,
hint_utils::{
get_integer_from_var_name, get_ptr_from_var_name, insert_value_from_var_name,
},
},
types::relocatable::MaybeRelocatable,
};
use cairo_vm::{
types::exec_scope::ExecutionScopes,
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use starknet_types_core::felt::NonZeroFelt;
use std::collections::HashMap;

use crate::hints::vars;

pub const HINT_DIVMOD_RLP: &str = "ids.q, ids.r = divmod(memory[ids.rlp + ids.i], ids.devisor)";

pub fn hint_divmod_rlp(
vm: &mut VirtualMachine,
_exec_scope: &mut ExecutionScopes,
hint_data: &HintProcessorData,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let rlp = get_ptr_from_var_name(
vars::ids::RLP,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let i: usize = get_integer_from_var_name(
vars::ids::I,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?
.try_into()
.unwrap();

let devisor = get_integer_from_var_name(
vars::ids::DEVISOR,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let (q, r) = vm
.get_integer((rlp + i)?)?
.div_rem(&NonZeroFelt::try_from(devisor).unwrap());

insert_value_from_var_name(
vars::ids::Q,
MaybeRelocatable::Int(q),
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

insert_value_from_var_name(
vars::ids::R,
MaybeRelocatable::Int(r),
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)
}

pub const HINT_DIVMOD_VALUE: &str = "ids.q, ids.r = divmod(memory[ids.value + ids.i], ids.devisor)";

pub fn hint_divmod_value(
vm: &mut VirtualMachine,
_exec_scope: &mut ExecutionScopes,
hint_data: &HintProcessorData,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let value = get_ptr_from_var_name(
vars::ids::VALUE,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let i: usize = get_integer_from_var_name(
vars::ids::I,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?
.try_into()
.unwrap();

let devisor = get_integer_from_var_name(
vars::ids::DEVISOR,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let (q, r) = vm
.get_integer((value + i)?)?
.div_rem(&NonZeroFelt::try_from(devisor).unwrap());

insert_value_from_var_name(
vars::ids::Q,
MaybeRelocatable::Int(q),
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

insert_value_from_var_name(
vars::ids::R,
MaybeRelocatable::Int(r),
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)
}
88 changes: 88 additions & 0 deletions cairo_vm_hints/src/hints/lib/rlp/item_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use crate::hints::vars;

use super::*;
use cairo_vm::{
hint_processor::builtin_hint_processor::{
builtin_hint_processor_definition::HintProcessorData,
hint_utils::{get_integer_from_var_name, insert_value_from_var_name},
},
types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable},
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use std::collections::HashMap;

pub const HINT_IS_LONG: &str =
"ids.is_long = 0 if 0xc0 <= ids.first_byte <= 0xf6 else 1 if 0xf7 <= ids.first_byte <= 0xff else assert False, 'Invalid RLP list'";

pub fn hint_is_long(
vm: &mut VirtualMachine,
_exec_scope: &mut ExecutionScopes,
hint_data: &HintProcessorData,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let first_byte = get_integer_from_var_name(
vars::ids::FIRST_BYTE,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let insert = if FELT_C0 <= first_byte && first_byte <= FELT_F6 {
Felt252::ZERO
} else if FELT_F7 <= first_byte && first_byte <= FELT_FF {
Felt252::ONE
} else {
return Err(HintError::UnknownIdentifier(
"Invalid RLP list".to_string().into_boxed_str(),
));
};

insert_value_from_var_name(
vars::ids::IS_LONG,
MaybeRelocatable::Int(insert),
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)
}

pub const HINT_ITEM_TYPE: &str = "ids.item_type = 0 if ids.current_item <= 0x7f else 1 if 0x80 <= ids.current_item <= 0xb6 else 2 if 0xb7 <= ids.current_item <= 0xbf else 3 if 0xc0 <= ids.current_item <= 0xf6 else 4 if 0xf7 <= ids.current_item <= 0xff else assert False, 'Invalid RLP item'";

pub fn hint_item_type(
vm: &mut VirtualMachine,
_exec_scope: &mut ExecutionScopes,
hint_data: &HintProcessorData,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let current_item = get_integer_from_var_name(
vars::ids::CURRENT_ITEM,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let insert = if current_item <= FELT_7F {
Felt252::ZERO
} else if FELT_80 <= current_item && current_item <= FELT_B6 {
Felt252::ONE // short string
} else if FELT_B7 <= current_item && current_item <= FELT_BF {
Felt252::TWO // long string
} else if FELT_C0 <= current_item && current_item <= FELT_F6 {
Felt252::THREE // short list
} else if FELT_F7 <= current_item && current_item <= FELT_FF {
FELT_4 // long list
} else {
return Err(HintError::UnknownIdentifier(
"Invalid RLP item".to_string().into_boxed_str(),
));
};

insert_value_from_var_name(
vars::ids::ITEM_TYPE,
MaybeRelocatable::Int(insert),
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)
}
16 changes: 16 additions & 0 deletions cairo_vm_hints/src/hints/lib/rlp/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pub mod divmod;
pub mod item_type;
pub mod processed_words;

use cairo_vm::Felt252;

pub const FELT_4: Felt252 = Felt252::from_hex_unchecked("0x04");
pub const FELT_7F: Felt252 = Felt252::from_hex_unchecked("0x7f");
pub const FELT_80: Felt252 = Felt252::from_hex_unchecked("0x80");
pub const FELT_B6: Felt252 = Felt252::from_hex_unchecked("0xb6");
pub const FELT_B7: Felt252 = Felt252::from_hex_unchecked("0xb7");
pub const FELT_BF: Felt252 = Felt252::from_hex_unchecked("0xbf");
pub const FELT_C0: Felt252 = Felt252::from_hex_unchecked("0xc0");
pub const FELT_F6: Felt252 = Felt252::from_hex_unchecked("0xf6");
pub const FELT_F7: Felt252 = Felt252::from_hex_unchecked("0xf7");
pub const FELT_FF: Felt252 = Felt252::from_hex_unchecked("0xff");
45 changes: 45 additions & 0 deletions cairo_vm_hints/src/hints/lib/rlp/processed_words.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use cairo_vm::{
hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData,
hint_processor::builtin_hint_processor::hint_utils::{
get_integer_from_var_name, insert_value_into_ap,
},
};
use cairo_vm::{
types::exec_scope::ExecutionScopes,
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use std::{cmp::Ordering, collections::HashMap};

use crate::hints::vars;

pub const HINT_PROCESSED_WORDS: &str =
"memory[ap] = 1 if (ids.value_len - ids.n_processed_words == 0) else 0";

pub fn hint_processed_words(
vm: &mut VirtualMachine,
_exec_scope: &mut ExecutionScopes,
hint_data: &HintProcessorData,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let value_len = get_integer_from_var_name(
vars::ids::VALUE_LEN,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let n_processed_words = get_integer_from_var_name(
vars::ids::N_PROCESSED_WORDS,
vm,
&hint_data.ids_data,
&hint_data.ap_tracking,
)?;

let insert = match (value_len - n_processed_words).cmp(&Felt252::ZERO) {
Ordering::Equal => Felt252::ONE,
_ => Felt252::ZERO,
};

insert_value_into_ap(vm, insert)
}
12 changes: 12 additions & 0 deletions cairo_vm_hints/src/hints/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,23 @@ pub mod ids {
pub(crate) const BUILTIN_PARAMS: &str = "builtin_params";
pub(crate) const BUILTIN_PTRS: &str = "builtin_ptrs";
pub(crate) const COMPILED_CLASS: &str = "compiled_class";
pub(crate) const CURRENT_ITEM: &str = "ids.current_item";
pub(crate) const DEVISOR: &str = "ids.devisor";
pub(crate) const FIRST_BYTE: &str = "ids.first_byte";
pub(crate) const I: &str = "ids.i";
pub(crate) const IS_LONG: &str = "ids.is_long";
pub(crate) const ITEM_TYPE: &str = "ids.item_type";
pub(crate) const N_BUILTINS: &str = "n_builtins";
pub(crate) const N_PROCESSED_WORDS: &str = "ids.n_processed_words";
pub(crate) const N_SELECTED_BUILTINS: &str = "n_selected_builtins";
pub(crate) const Q: &str = "ids.q";
pub(crate) const R: &str = "ids.r";
pub(crate) const RETURN_BUILTIN_PTRS: &str = "return_builtin_ptrs";
pub(crate) const RLP: &str = "ids.rlp";
pub(crate) const SELECT_BUILTIN: &str = "select_builtin";
pub(crate) const SELECTED_ENCODINGS: &str = "selected_encodings";
pub(crate) const SELECTED_PTRS: &str = "selected_ptrs";
pub(crate) const SYSCALL_PTR: &str = "syscall_ptr";
pub(crate) const VALUE_LEN: &str = "ids.value_len";
pub(crate) const VALUE: &str = "ids.value";
}
32 changes: 18 additions & 14 deletions src/utils/rlp.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ func rlp_list_retrieve{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, pow2_array
let current_item = extract_byte_at_pos(rlp[item_starts_at_word], item_start_offset, pow2_array);

local item_type: felt;
// %{
// #print("current item:", hex(ids.current_item))
// %}
%{
#print("current item:", hex(ids.current_item))
if ids.current_item <= 0x7f:
ids.item_type = 0 # single byte
elif 0x80 <= ids.current_item <= 0xb6:
Expand Down Expand Up @@ -274,7 +276,7 @@ func chunk_to_felt_be{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, pow2_array:
}

let (q, r) = felt_divmod(value, 0x100); // remove trailing byte
%{ print("q:", hex(ids.q), "r:", hex(ids.r)) %}
// %{ print("q:", hex(ids.q), "r:", hex(ids.r)) %}

// ensure we have a short string
assert [range_check_ptr] = 8 - bytes_len;
Expand Down Expand Up @@ -328,14 +330,14 @@ func decode_rlp_word_to_uint256{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, p
) -> Uint256 {
alloc_locals;

%{ print("decode_rlp_word_to_uint256") %}
%{ print(hex(memory[ids.rlp])) %}
// %{ print("decode_rlp_word_to_uint256") %}
// %{ print(hex(memory[ids.rlp])) %}

let (value, value_len, value_bytes_len) = rlp_list_retrieve(
rlp=rlp, field=0, item_starts_at_byte=0, counter=0
);

%{ print("value:", hex(memory[ids.value])) %}
// %{ print("value:", hex(memory[ids.value])) %}

// convert to uint256
let result = le_chunks_to_uint256(
Expand Down Expand Up @@ -450,10 +452,10 @@ func right_shift_le_chunks{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, pow2_a
// Inlined felt_divmod (unsigned_div_rem).
let q = [ap];
let r = [ap + 1];
%{
ids.q, ids.r = divmod(memory[ids.value + ids.i], ids.devisor)
#print(f"val={memory[ids.value + ids.i]} q={ids.q} r={ids.r} i={ids.i}")
%}
%{ ids.q, ids.r = divmod(memory[ids.value + ids.i], ids.devisor) %}
// %{
// #print(f"val={memory[ids.value + ids.i]} q={ids.q} r={ids.r} i={ids.i}")
// %}
ap += 2;
tempvar offset = 3 * n_processed_words;
assert [range_check_ptr + offset] = q;
Expand Down Expand Up @@ -520,10 +522,10 @@ func prepend_le_chunks{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, pow2_array
// Inlined felt_divmod (unsigned_div_rem).
let q = [ap];
let r = [ap + 1];
%{
ids.q, ids.r = divmod(memory[ids.rlp + ids.i], ids.devisor)
#print(f"val={hex(memory[ids.rlp + ids.i])} q/cur={hex(ids.q)} r={hex(ids.r)} i={ids.i}")
%}
%{ ids.q, ids.r = divmod(memory[ids.rlp + ids.i], ids.devisor) %}
// %{
// print(f"val={hex(memory[ids.rlp + ids.i])} q/cur={hex(ids.q)} r={hex(ids.r)} i={ids.i}")
// %}
ap += 2;
tempvar item_bytes_len = 3 * n_processed_words;
assert [range_check_ptr + item_bytes_len] = q;
Expand Down Expand Up @@ -612,8 +614,10 @@ func get_rlp_len{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, pow2_array: felt
let current_item = extract_byte_at_pos(rlp[0], item_start_offset, pow2_array);

local item_type: felt;
// %{
// #print("current item:", hex(ids.current_item))
// %}
%{
#print("current item:", hex(ids.current_item))
if ids.current_item <= 0x7f:
ids.item_type = 0 # single byte
elif 0x80 <= ids.current_item <= 0xb6:
Expand Down

0 comments on commit 697ac49

Please sign in to comment.