Skip to content

Commit

Permalink
Add hint U256InvModN to Cairo1HintProcessor (#1744)
Browse files Browse the repository at this point in the history
* Add test

* Add hint

* Add Changelog entry

* fmt

* Move code to method

* fmt
  • Loading branch information
fmoletta committed May 7, 2024
1 parent bc5a14e commit 258dd84
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: Add hint `U256InvModN` to `Cairo1HintProcessor` [#1744](https://github.com/lambdaclass/cairo-vm/pull/1744)

* perf: use a more compact representation for `MemoryCell` [#1672](https://github.com/lambdaclass/cairo-vm/pull/1672)
* BREAKING: `Memory::get_value` will now always return `Cow::Owned` variants, code that relied on `Cow::Borrowed` may break

Expand Down
5 changes: 5 additions & 0 deletions cairo1-run/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ mod tests {
use rstest::rstest;

#[rstest]
#[case(
"ecdsa_recover.cairo",
"3490001189944926769628658346285649224182856084131963744896357527096042836716",
None
)]
#[case("tensor_new.cairo", "[1 2] [1 false 1 true]", None)]
#[case("bytes31_ret.cairo", "123", None)]
#[case("null_ret.cairo", "null", None)]
Expand Down
7 changes: 7 additions & 0 deletions cairo_programs/cairo-1-programs/ecdsa_recover.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

fn main() -> felt252 {
let message_hash: felt252 = 0x503f4bea29baee10b22a7f10bdc82dda071c977c1f25b8f3973d34e6b03b2c;
let signature_r: felt252 = 0xbe96d72eb4f94078192c2e84d5230cde2a70f4b45c8797e2c907acff5060bb;
let signature_s: felt252 = 0x677ae6bba6daf00d2631fab14c8acf24be6579f9d9e98f67aa7f2770e57a1f5;
core::ecdsa::recover_public_key(:message_hash, :signature_r, :signature_s, y_parity: false).unwrap()
}
102 changes: 98 additions & 4 deletions vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use cairo_lang_casm::{
use core::any::Any;
use core::ops::Shl;

use num_bigint::BigUint;
use num_integer::Integer;
use num_traits::ToPrimitive;
use num_bigint::{BigInt, BigUint};
use num_integer::{ExtendedGcd, Integer};
use num_traits::{Signed, ToPrimitive};

/// Execution scope for constant memory allocation.
struct MemoryExecScope {
Expand Down Expand Up @@ -242,6 +242,30 @@ impl Cairo1HintProcessor {
vm, dividend0, dividend1, dividend2, dividend3, divisor0, divisor1, quotient0,
quotient1, quotient2, quotient3, remainder0, remainder1,
),
Hint::Core(CoreHintBase::Core(CoreHint::U256InvModN {
b0,
b1,
n0,
n1,
g0_or_no_inv,
g1_option,
s_or_r0,
s_or_r1,
t_or_k0,
t_or_k1,
})) => self.u256_inv_mod_n(
vm,
b0,
b1,
n0,
n1,
g0_or_no_inv,
g1_option,
s_or_r0,
s_or_r1,
t_or_k0,
t_or_k1,
),

hint => Err(HintError::UnknownHint(
format!("{:?}", hint).into_boxed_str(),
Expand Down Expand Up @@ -397,7 +421,6 @@ impl Cairo1HintProcessor {
dict_manager_exec_scope.finalize_segment(vm, dict_address)
}

#[allow(clippy::too_many_arguments)]
#[allow(clippy::too_many_arguments)]
fn uint256_div_mod(
&self,
Expand Down Expand Up @@ -1076,6 +1099,77 @@ impl Cairo1HintProcessor {
)
.map_err(HintError::from)
}

#[allow(clippy::too_many_arguments)]
fn u256_inv_mod_n(
&self,
vm: &mut VirtualMachine,
b0: &ResOperand,
b1: &ResOperand,
n0: &ResOperand,
n1: &ResOperand,
g0_or_no_inv: &CellRef,
g1_option: &CellRef,
s_or_r0: &CellRef,
s_or_r1: &CellRef,
t_or_k0: &CellRef,
t_or_k1: &CellRef,
) -> Result<(), HintError> {
let pow_2_128 = BigInt::from(u128::MAX) + 1u32;
let b0 = get_val(vm, b0)?.to_bigint();
let b1 = get_val(vm, b1)?.to_bigint();
let n0 = get_val(vm, n0)?.to_bigint();
let n1 = get_val(vm, n1)?.to_bigint();
let b: BigInt = b0.clone() + b1.clone().shl(128);
let n: BigInt = n0 + n1.shl(128);
let ExtendedGcd {
gcd: mut g,
x: _,
y: mut r,
} = n.extended_gcd(&b);
if n == 1.into() {
vm.insert_value(cell_ref_to_relocatable(s_or_r0, vm)?, Felt252::from(b0))?;
vm.insert_value(cell_ref_to_relocatable(s_or_r1, vm)?, Felt252::from(b1))?;
vm.insert_value(cell_ref_to_relocatable(t_or_k0, vm)?, Felt252::from(1))?;
vm.insert_value(cell_ref_to_relocatable(t_or_k1, vm)?, Felt252::from(0))?;
vm.insert_value(cell_ref_to_relocatable(g0_or_no_inv, vm)?, Felt252::from(1))?;
vm.insert_value(cell_ref_to_relocatable(g1_option, vm)?, Felt252::from(0))?;
} else if g != 1.into() {
// This makes sure `g0_or_no_inv` is always non-zero in the no inverse case.
if g.is_even() {
g = 2u32.into();
}
let (limb1, limb0) = (&b / &g).div_rem(&pow_2_128);
vm.insert_value(cell_ref_to_relocatable(s_or_r0, vm)?, Felt252::from(limb0))?;
vm.insert_value(cell_ref_to_relocatable(s_or_r1, vm)?, Felt252::from(limb1))?;
let (limb1, limb0) = (&n / &g).div_rem(&pow_2_128);
vm.insert_value(cell_ref_to_relocatable(t_or_k0, vm)?, Felt252::from(limb0))?;
vm.insert_value(cell_ref_to_relocatable(t_or_k1, vm)?, Felt252::from(limb1))?;
let (limb1, limb0) = g.div_rem(&pow_2_128);
vm.insert_value(
cell_ref_to_relocatable(g0_or_no_inv, vm)?,
Felt252::from(limb0),
)?;
vm.insert_value(
cell_ref_to_relocatable(g1_option, vm)?,
Felt252::from(limb1),
)?;
} else {
r %= &n;
if r.is_negative() {
r += &n;
}
let k: BigInt = (&r * b - 1) / n;
let (limb1, limb0) = r.div_rem(&pow_2_128);
vm.insert_value(cell_ref_to_relocatable(s_or_r0, vm)?, Felt252::from(limb0))?;
vm.insert_value(cell_ref_to_relocatable(s_or_r1, vm)?, Felt252::from(limb1))?;
let (limb1, limb0) = k.div_rem(&pow_2_128);
vm.insert_value(cell_ref_to_relocatable(t_or_k0, vm)?, Felt252::from(limb0))?;
vm.insert_value(cell_ref_to_relocatable(t_or_k1, vm)?, Felt252::from(limb1))?;
vm.insert_value(cell_ref_to_relocatable(g0_or_no_inv, vm)?, Felt252::from(0))?;
}
Ok(())
}
}

impl HintProcessorLogic for Cairo1HintProcessor {
Expand Down

0 comments on commit 258dd84

Please sign in to comment.