Skip to content

Commit

Permalink
Add NewHint#13
Browse files Browse the repository at this point in the history
  • Loading branch information
MegaRedHand committed Apr 18, 2023
1 parent a993318 commit b1a9971
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 5 deletions.
31 changes: 31 additions & 0 deletions cairo_programs/quad_bit.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
%builtins range_check

func get_quad_bit{range_check_ptr}(scalar_u: felt, scalar_v: felt, m: felt) -> felt {
alloc_locals;
local quad_bit: felt;
%{
ids.quad_bit = (
8 * ((ids.scalar_v >> ids.m) & 1)
+ 4 * ((ids.scalar_u >> ids.m) & 1)
+ 2 * ((ids.scalar_v >> (ids.m - 1)) & 1)
+ ((ids.scalar_u >> (ids.m - 1)) & 1)
)
%}
return quad_bit;
}

func test_quad_bit{range_check_ptr}() {
let u = 4194304; // 1 << 22
let v = 8388608; // 1 << 23

// 8 * 1 + 4 * 0 + 2 * 0 + 1 * 1
assert get_quad_bit(u, v, 23) = 9;

return ();
}

func main{range_check_ptr}() {
test_quad_bit();

return ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ use felt::Felt252;
#[cfg(feature = "skip_next_instruction_hint")]
use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction;

use super::secp::ec_utils::quad_bit;

pub struct HintProcessorData {
pub code: String,
pub ap_tracking: ApTracking,
Expand Down Expand Up @@ -522,6 +524,7 @@ impl HintProcessor for BuiltinHintProcessor {
hint_code::UINT256_MUL_DIV_MOD => {
uint256_mul_div_mod(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::QUAD_BIT => quad_bit(vm, &hint_data.ids_data, &hint_data.ap_tracking),
#[cfg(feature = "skip_next_instruction_hint")]
hint_code::SKIP_NEXT_INSTRUCTION => skip_next_instruction(vm),
code => Err(HintError::UnknownHint(code.to_string())),
Expand Down
7 changes: 7 additions & 0 deletions src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,5 +776,12 @@ ids.root.d1 = root_split[1]
ids.root.d2 = root_split[2]";
pub const UINT384_SIGNED_NN: &str = "memory[ap] = 1 if 0 <= (ids.a.d2 % PRIME) < 2 ** 127 else 0";

pub const QUAD_BIT: &str = r#"ids.quad_bit = (
8 * ((ids.scalar_v >> ids.m) & 1)
+ 4 * ((ids.scalar_u >> ids.m) & 1)
+ 2 * ((ids.scalar_v >> (ids.m - 1)) & 1)
+ ((ids.scalar_u >> (ids.m - 1)) & 1)
)"#;

#[cfg(feature = "skip_next_instruction_hint")]
pub const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()";
77 changes: 72 additions & 5 deletions src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ use crate::{
hint_processor::{
builtin_hint_processor::{
hint_utils::{
get_integer_from_var_name, get_relocatable_from_var_name, insert_value_into_ap,
get_integer_from_var_name, get_relocatable_from_var_name,
insert_value_from_var_name, insert_value_into_ap,
},
secp::{
bigint_utils::BigInt3,
secp_utils::{pack, SECP_P},
},
secp::secp_utils::pack,
},
hint_processor_definition::HintReference,
},
Expand All @@ -18,9 +22,7 @@ use crate::{
use felt::Felt252;
use num_bigint::BigInt;
use num_integer::Integer;
use num_traits::{One, Zero};

use super::{bigint_utils::BigInt3, secp_utils::SECP_P};
use num_traits::{One, ToPrimitive, Zero};

#[derive(Debug, PartialEq)]
struct EcPoint<'a> {
Expand Down Expand Up @@ -272,6 +274,48 @@ pub fn ec_mul_inner(
insert_value_into_ap(vm, scalar)
}

/*
Implements hint:
%{
ids.quad_bit = (
8 * ((ids.scalar_v >> ids.m) & 1)
+ 4 * ((ids.scalar_u >> ids.m) & 1)
+ 2 * ((ids.scalar_v >> (ids.m - 1)) & 1)
+ ((ids.scalar_u >> (ids.m - 1)) & 1)
)
%}
*/
pub fn quad_bit(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let scalar_v_cow = get_integer_from_var_name("scalar_v", vm, ids_data, ap_tracking)?;
let scalar_u_cow = get_integer_from_var_name("scalar_u", vm, ids_data, ap_tracking)?;
let m_cow = get_integer_from_var_name("m", vm, ids_data, ap_tracking)?;

let scalar_v = scalar_v_cow.as_ref();
let scalar_u = scalar_u_cow.as_ref();
let Some(m) = m_cow.as_ref().to_u32() else {
return insert_value_from_var_name("quad_bit", 0, vm, ids_data, ap_tracking);
};

let one = &Felt252::one();

// 8 * ((ids.scalar_v >> ids.m) & 1)
let quad_bit_3 = ((scalar_v >> m) & one) << 3u32;
// 4 * ((ids.scalar_u >> ids.m) & 1)
let quad_bit_2 = ((scalar_u >> m) & one) << 2u32;
// 2 * ((ids.scalar_v >> (ids.m - 1)) & 1)
let quad_bit_1 = ((scalar_v >> (m - 1)) & one) << 1u32;
// 1 * ((ids.scalar_u >> (ids.m - 1)) & 1)
let quad_bit_0 = (scalar_u >> (m - 1)) & one;

let res = quad_bit_0 + quad_bit_1 + quad_bit_2 + quad_bit_3;

insert_value_from_var_name("quad_bit", res, vm, ids_data, ap_tracking)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -809,4 +853,27 @@ mod tests {
let r = EcPoint::from_var_name("e", &vm, &ids_data, &ap_tracking);
assert_matches!(r, Err(HintError::UnknownIdentifier(x)) if x == "e")
}

#[test]
fn run_quad_bit_ok() {
let hint_code = "ids.quad_bit = (\n 8 * ((ids.scalar_v >> ids.m) & 1)\n + 4 * ((ids.scalar_u >> ids.m) & 1)\n + 2 * ((ids.scalar_v >> (ids.m - 1)) & 1)\n + ((ids.scalar_u >> (ids.m - 1)) & 1)\n)";
let mut vm = vm_with_range_check!();

let scalar_u = 89712;
let scalar_v = 1478396;
let m = 4;
// Insert ids.scalar into memory
vm.segments = segments![((1, 0), scalar_u), ((1, 1), scalar_v), ((1, 2), m)];

// Initialize RunContext
run_context!(vm, 0, 4, 4);

let ids_data = ids_data!["scalar_u", "scalar_v", "m", "quad_bit"];

// Execute the hint
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));

// Check hint memory inserts
check_memory![vm.segments.memory, ((1, 3), 14)];
}
}
7 changes: 7 additions & 0 deletions src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1329,3 +1329,10 @@ fn cairo_run_div_mod_n() {
let program_data = include_bytes!("../../cairo_programs/div_mod_n.json");
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_quad_bit() {
let program_data = include_bytes!("../../cairo_programs/quad_bit.json");
run_program_simple(program_data.as_slice());
}

0 comments on commit b1a9971

Please sign in to comment.