From 18a0fc096176283fb93662d341bde68ae23d0c38 Mon Sep 17 00:00:00 2001 From: shryasss Date: Sat, 3 Feb 2024 16:08:30 +0530 Subject: [PATCH 01/24] feat: added expand msg impl --- halo2-ecc/Cargo.toml | 1 + .../src/secp256k1/hash_to_curve/constants.rs | 21 + .../hash_to_curve/expand_message_xmd.rs | 132 ++++ halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 3 + halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 53 ++ halo2-ecc/src/secp256k1/mod.rs | 3 + halo2-ecc/src/secp256k1/sha256/compression.rs | 609 ++++++++++++++++++ halo2-ecc/src/secp256k1/sha256/mod.rs | 209 ++++++ halo2-ecc/src/secp256k1/sha256/spread.rs | 101 +++ halo2-ecc/src/secp256k1/util.rs | 50 ++ 10 files changed, 1182 insertions(+) create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/constants.rs create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/mod.rs create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/util.rs create mode 100644 halo2-ecc/src/secp256k1/sha256/compression.rs create mode 100644 halo2-ecc/src/secp256k1/sha256/mod.rs create mode 100644 halo2-ecc/src/secp256k1/sha256/spread.rs create mode 100644 halo2-ecc/src/secp256k1/util.rs diff --git a/halo2-ecc/Cargo.toml b/halo2-ecc/Cargo.toml index fba53531..0ae1610a 100644 --- a/halo2-ecc/Cargo.toml +++ b/halo2-ecc/Cargo.toml @@ -26,6 +26,7 @@ halo2-base = { version = "=0.4.1", path = "../halo2-base", default-features = fa # plotting circuit layout plotters = { version = "0.3.0", optional = true } +sha2 = "0.10.8" [dev-dependencies] ark-std = { version = "0.3.0", features = ["print-trace"] } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs new file mode 100644 index 00000000..eec0dfe5 --- /dev/null +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -0,0 +1,21 @@ +use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; + +pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { + let zero = ctx.load_zero(); + vec![zero; 64] +} + +pub(crate) fn get_lib_str(ctx: &mut Context) -> Vec> { + let zero = ctx.load_zero(); + let ninety_six = ctx.load_constant(F::from(96)); + vec![zero, ninety_six] +} + +pub(crate) fn get_dst_prime(ctx: &mut Context) -> Vec> { + let dst_prime = [ + 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, + 99, 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, + 87, 85, 95, 82, 79, 95, 49, + ]; + dst_prime.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>() +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs new file mode 100644 index 00000000..ab73b90a --- /dev/null +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -0,0 +1,132 @@ +use halo2_base::{ + gates::{GateInstructions, RangeChip, RangeInstructions}, + utils::BigPrimeField, + AssignedValue, Context, QuantumCell, +}; + +use crate::secp256k1::sha256::Sha256Chip; + +use super::{ + constants::{get_dst_prime, get_lib_str, get_z_pad}, + util::{bits_le_to_bytes_assigned, bytes_to_bits_le_assigned}, +}; + +fn msg_prime( + ctx: &mut Context, + msg_bytes: &[AssignedValue], +) -> Vec> { + let zero = ctx.load_zero(); + + let z_pad = get_z_pad(ctx); + let lib_str = get_lib_str(ctx); + let dst_prime = get_dst_prime(ctx); + + let mut msg_prime = Vec::>::new(); + + // msg_prme = z_pad ... + msg_prime.extend(z_pad); + + // msg_prme = z_pad || msg ... + msg_prime.extend(msg_bytes); + + // msg_prme = z_pad || msg || lib_str ... + msg_prime.extend(lib_str); + + // msg_prme = z_pad || msg || lib_str || 0 ... + msg_prime.push(zero); + + // msg_prme = z_pad || msg || lib_str || 0 || dst_prime + msg_prime.extend(dst_prime); + + msg_prime +} + +fn hash_msg_prime_to_b0( + ctx: &mut Context, + sha256_chip: &Sha256Chip<'_, F>, + msg_prime_bytes: &[AssignedValue], +) -> Vec> { + let msg_prime_bytes = msg_prime_bytes.iter().map(|byte| QuantumCell::Existing(*byte)); + let hash = sha256_chip.digest(ctx, msg_prime_bytes).unwrap(); + hash +} + +fn hash_bi( + ctx: &mut Context, + range: &RangeChip, + sha256_chip: &Sha256Chip, + b_idx_byte: &AssignedValue, + b0_bytes: &[AssignedValue], + bi_minus_one_bytes: &[AssignedValue], +) -> Vec> { + let b0_bits = bytes_to_bits_le_assigned(ctx, range, b0_bytes); + let bi_minus_one_bits = bytes_to_bits_le_assigned(ctx, range, bi_minus_one_bytes); + + let mut xor_bits = Vec::>::new(); + for (bo_bit, bi_minus_one_bit) in b0_bits.iter().zip(bi_minus_one_bits.iter()) { + let res = range.gate().xor(ctx, *bo_bit, *bi_minus_one_bit); + xor_bits.push(res); + } + let xor_bytes = bits_le_to_bytes_assigned(ctx, range, &xor_bits); + + let bi_bytes = hash_b(ctx, sha256_chip, b_idx_byte, &xor_bytes); + + bi_bytes +} + +fn hash_b<'a, F: BigPrimeField>( + ctx: &mut Context, + sha256_chip: &Sha256Chip<'a, F>, + b_idx_byte: &AssignedValue, + b_bytes: &Vec>, +) -> Vec> { + let dst_prime = get_dst_prime(ctx); + + let mut preimage = Vec::>::new(); + preimage.extend(b_bytes); + preimage.push(*b_idx_byte); + preimage.extend(dst_prime); + + let preimage = preimage.iter().map(|byte| QuantumCell::Existing(*byte)); + let hash = sha256_chip.digest(ctx, preimage).unwrap(); + + hash +} + +fn str_xor( + ctx: &mut Context, + range: &RangeChip, + a_bits: &[AssignedValue], + b_bits: &[AssignedValue], +) -> Vec> { + assert_eq!(a_bits.len(), b_bits.len()); + + let gate = range.gate(); + + let mut xor = Vec::>::new(); + for (a_bit, b_bit) in a_bits.iter().zip(b_bits.iter()) { + let res = gate.xor(ctx, *a_bit, *b_bit); + xor.push(res); + } + + xor +} + +fn expand_message_xmd( + ctx: &mut Context, + range: &RangeChip, + sha256_chip: &Sha256Chip, + msg_bytes: &[AssignedValue], +) -> Vec> { + let one = ctx.load_constant(F::from(1)); + let two = ctx.load_constant(F::from(2)); + let three = ctx.load_constant(F::from(3)); + + let msg_prime_bytes = msg_prime(ctx, msg_bytes); + let b0 = hash_msg_prime_to_b0(ctx, sha256_chip, &msg_prime_bytes); + let b1 = hash_b(ctx, sha256_chip, &one, &b0); + let b2 = hash_bi(ctx, range, sha256_chip, &two, &b0, &b1); + let b3 = hash_bi(ctx, range, sha256_chip, &three, &b0, &b2); + + [b1, b2, b3].concat() +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs new file mode 100644 index 00000000..dad19c76 --- /dev/null +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -0,0 +1,3 @@ +pub mod constants; +pub mod expand_message_xmd; +pub mod util; diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs new file mode 100644 index 00000000..a695307b --- /dev/null +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -0,0 +1,53 @@ +use halo2_base::{ + gates::{GateInstructions, RangeChip, RangeInstructions}, + utils::BigPrimeField, + AssignedValue, Context, QuantumCell, +}; +use itertools::Itertools; + +use crate::secp256k1::util::{bits_le_to_fe_assigned, fe_to_bits_le}; + +pub fn byte_to_bits_le_assigned( + ctx: &mut Context, + range: &RangeChip, + byte: &AssignedValue, +) -> Vec> { + let bits = fe_to_bits_le(byte.value(), 8); + let assigned_bits = + bits.iter().map(|bit| ctx.load_constant(F::from(*bit as u64))).collect_vec(); + + let _byte = bits_le_to_fe_assigned(ctx, range, &assigned_bits).unwrap(); + ctx.constrain_equal(byte, &_byte); + + assigned_bits +} + +pub fn bytes_to_bits_le_assigned( + ctx: &mut Context, + range: &RangeChip, + bytes: &[AssignedValue], +) -> Vec> { + bytes.iter().flat_map(|byte| byte_to_bits_le_assigned(ctx, range, byte)).collect_vec() +} + +pub fn bits_le_to_byte_assigned( + ctx: &mut Context, + range: &RangeChip, + bits: &[AssignedValue], +) -> AssignedValue { + assert_eq!(bits.len(), 8); + let gate = range.gate(); + let mut sum = ctx.load_zero(); + for (idx, bit) in bits.iter().enumerate() { + sum = gate.mul_add(ctx, *bit, QuantumCell::Constant(F::from(1 << idx)), sum); + } + sum +} + +pub fn bits_le_to_bytes_assigned( + ctx: &mut Context, + range: &RangeChip, + bits: &[AssignedValue], +) -> Vec> { + bits.chunks(8).map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)).collect_vec() +} diff --git a/halo2-ecc/src/secp256k1/mod.rs b/halo2-ecc/src/secp256k1/mod.rs index ca4528e4..38970d20 100644 --- a/halo2-ecc/src/secp256k1/mod.rs +++ b/halo2-ecc/src/secp256k1/mod.rs @@ -8,5 +8,8 @@ pub type FqChip<'range, F> = fp::FpChip<'range, F, Fq>; pub type Secp256k1Chip<'chip, F> = ecc::EccChip<'chip, F, FpChip<'chip, F>>; pub const SECP_B: u64 = 7; +pub mod hash_to_curve; +pub mod sha256; #[cfg(test)] mod tests; +pub mod util; diff --git a/halo2-ecc/src/secp256k1/sha256/compression.rs b/halo2-ecc/src/secp256k1/sha256/compression.rs new file mode 100644 index 00000000..ecfc97d0 --- /dev/null +++ b/halo2-ecc/src/secp256k1/sha256/compression.rs @@ -0,0 +1,609 @@ +use halo2_base::{ + gates::{GateInstructions, RangeInstructions}, + halo2_proofs::plonk::Error, + utils::BigPrimeField, + AssignedValue, Context, QuantumCell, +}; +use itertools::Itertools; + +use crate::secp256k1::util::{bits_le_to_fe, fe_to_bits_le}; + +use super::spread::SpreadChip; + +pub const NUM_ROUND: usize = 64; +pub const NUM_STATE_WORD: usize = 8; +const ROUND_CONSTANTS: [u32; NUM_ROUND] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; + +pub const INIT_STATE: [u32; NUM_STATE_WORD] = [ + 0x6a09_e667, + 0xbb67_ae85, + 0x3c6e_f372, + 0xa54f_f53a, + 0x510e_527f, + 0x9b05_688c, + 0x1f83_d9ab, + 0x5be0_cd19, +]; + +pub type SpreadU32<'a, F> = (AssignedValue, AssignedValue); + +pub fn sha256_compression<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + assigned_input_bytes: &[AssignedValue], + pre_state_words: &[AssignedValue], +) -> Result>, Error> { + debug_assert_eq!(assigned_input_bytes.len(), 64); + debug_assert_eq!(pre_state_words.len(), 8); + let range = spread_chip.range(); + let gate = range.gate(); + // message schedule. + let mut i = 0; + let mut message_u32s = assigned_input_bytes + .chunks(4) + .map(|bytes| { + let mut sum = ctx.load_zero(); + for idx in 0..4 { + sum = gate.mul_add( + ctx, + QuantumCell::Existing(bytes[3 - idx]), + QuantumCell::Constant(F::from(1u64 << (8 * idx))), + QuantumCell::Existing(sum), + ); + } + i += 1; + // println!("idx {} sum {:?}", i, sum.value()); + sum + }) + .collect_vec(); + + // let mut message_bits = message_u32s + // .iter() + // .map(|val: &AssignedValue| gate.num_to_bits(ctx, val, 32)) + // .collect_vec(); + let mut message_spreads = message_u32s + .iter() + .map(|dense| state_to_spread_u32(ctx, spread_chip, dense)) + .collect::>, Error>>()?; + for idx in 16..64 { + // let w_2_spread = state_to_spread_u32(ctx, range, ctx_spread, &message_u32s[idx - 2])?; + // let w_15_spread = state_to_spread_u32(ctx, range, ctx_spread, &message_u32s[idx - 15])?; + let term1 = sigma_lower1(ctx, spread_chip, &message_spreads[idx - 2])?; + let term3 = sigma_lower0(ctx, spread_chip, &message_spreads[idx - 15])?; + // let term1_u32 = bits2u32(ctx, gate, &term1_bits); + // let term3_u32 = bits2u32(ctx, gate, &term3_bits); + let new_w = { + let mut sum = gate.add(ctx, term1, message_u32s[idx - 7]); + sum = gate.add(ctx, sum, term3); + sum = gate.add(ctx, sum, message_u32s[idx - 16]); + mod_u32(ctx, range, &sum) + }; + // println!( + // "idx {} term1 {:?}, term3 {:?}, new_w {:?}", + // idx, + // term1.value(), + // term3.value(), + // new_w.value() + // ); + message_u32s.push(new_w); + let new_w_spread = state_to_spread_u32(ctx, spread_chip, &new_w)?; + message_spreads.push(new_w_spread); + // if idx <= 61 { + // let new_w_bits = gate.num_to_bits(ctx, &new_w, 32); + // message_bits.push(new_w_bits); + // } + } + + // compression + let (mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h) = ( + pre_state_words[0], + pre_state_words[1], + pre_state_words[2], + pre_state_words[3], + pre_state_words[4], + pre_state_words[5], + pre_state_words[6], + pre_state_words[7], + ); + let mut a_spread = state_to_spread_u32(ctx, spread_chip, &a)?; + let mut b_spread = state_to_spread_u32(ctx, spread_chip, &b)?; + let mut c_spread = state_to_spread_u32(ctx, spread_chip, &c)?; + // let mut d_spread = state_to_spread_u32(ctx, range, ctx_spread, &d)?; + let mut e_spread = state_to_spread_u32(ctx, spread_chip, &e)?; + let mut f_spread = state_to_spread_u32(ctx, spread_chip, &f)?; + let mut g_spread = state_to_spread_u32(ctx, spread_chip, &g)?; + // let mut h_spread = state_to_spread_u32(ctx, range, ctx_spread, &h)?; + // let mut a_bits = gate.num_to_bits(ctx, &a, 32); + // let mut b_bits = gate.num_to_bits(ctx, &b, 32); + // let mut c_bits = gate.num_to_bits(ctx, &c, 32); + // let mut e_bits = gate.num_to_bits(ctx, &e, 32); + // let mut f_bits = gate.num_to_bits(ctx, &f, 32); + // let mut g_bits = gate.num_to_bits(ctx, &g, 32); + #[allow(unused_assignments)] + let mut t1 = ctx.load_zero(); + #[allow(unused_assignments)] + let mut t2 = ctx.load_zero(); + for idx in 0..64 { + t1 = { + // let e_spread = state_to_spread_u32(ctx, range, ctx_spread, &e)?; + // let f_spread = state_to_spread_u32(ctx, range, ctx_spread, &f)?; + // let g_spread = state_to_spread_u32(ctx, range, ctx_spread, &g)?; + let sigma_term = sigma_upper1(ctx, spread_chip, &e_spread)?; + let ch_term = ch(ctx, spread_chip, &e_spread, &f_spread, &g_spread)?; + // println!( + // "idx {} sigma {:?} ch {:?}", + // idx, + // sigma_term.value(), + // ch_term.value() + // ); + let add1 = gate.add(ctx, h, sigma_term); + let add2 = gate.add(ctx, QuantumCell::Existing(add1), QuantumCell::Existing(ch_term)); + let add3 = gate.add( + ctx, + QuantumCell::Existing(add2), + QuantumCell::Constant(F::from(ROUND_CONSTANTS[idx] as u64)), + ); + let add4 = gate.add( + ctx, + QuantumCell::Existing(add3), + QuantumCell::Existing(message_u32s[idx]), + ); + mod_u32(ctx, range, &add4) + }; + t2 = { + // let a_spread = state_to_spread_u32(ctx, range, ctx_spread, &a)?; + // let b_spread = state_to_spread_u32(ctx, range, ctx_spread, &b)?; + // let c_spread = state_to_spread_u32(ctx, range, ctx_spread, &c)?; + let sigma_term = sigma_upper0(ctx, spread_chip, &a_spread)?; + let maj_term = maj(ctx, spread_chip, &a_spread, &b_spread, &c_spread)?; + let add = + gate.add(ctx, QuantumCell::Existing(sigma_term), QuantumCell::Existing(maj_term)); + mod_u32(ctx, range, &add) + }; + // println!("idx {}, t1 {:?}, t2 {:?}", idx, t1.value(), t2.value()); + h = g; + // h_spread = g_spread; + g = f; + g_spread = f_spread; + f = e; + f_spread = e_spread; + e = { + let add = gate.add(ctx, QuantumCell::Existing(d), QuantumCell::Existing(t1)); + mod_u32(ctx, range, &add) + }; + e_spread = state_to_spread_u32(ctx, spread_chip, &e)?; + d = c; + // d_spread = c_spread; + c = b; + c_spread = b_spread; + b = a; + b_spread = a_spread; + a = { + let add = gate.add(ctx, QuantumCell::Existing(t1), QuantumCell::Existing(t2)); + mod_u32(ctx, range, &add) + }; + a_spread = state_to_spread_u32(ctx, spread_chip, &a)?; + } + let new_states = [a, b, c, d, e, f, g, h]; + let next_state_words = new_states + .iter() + .copied() + .zip(pre_state_words.iter().copied()) + .map(|(x, y)| { + let add = gate.add(ctx, QuantumCell::Existing(x), QuantumCell::Existing(y)); + // println!( + // "pre {:?} new {:?} add {:?}", + // y.value(), + // x.value(), + // add.value() + // ); + mod_u32(ctx, range, &add) + }) + .collect_vec(); + Ok(next_state_words) +} + +fn state_to_spread_u32<'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x: &AssignedValue, +) -> Result, Error> { + let gate = spread_chip.range().gate(); + let lo = F::from((x.value().get_lower_32() & ((1 << 16) - 1)) as u64); + let hi = F::from((x.value().get_lower_32() >> 16) as u64); + let assigned_lo = ctx.load_witness(lo); + let assigned_hi = ctx.load_witness(hi); + let composed = gate.mul_add( + ctx, + QuantumCell::Existing(assigned_hi), + QuantumCell::Constant(F::from(1u64 << 16)), + QuantumCell::Existing(assigned_lo), + ); + ctx.constrain_equal(x, &composed); + let lo_spread = spread_chip.spread(ctx, &assigned_lo)?; + let hi_spread = spread_chip.spread(ctx, &assigned_hi)?; + Ok((lo_spread, hi_spread)) +} + +fn mod_u32<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + range: &impl RangeInstructions, + x: &AssignedValue, +) -> AssignedValue { + let gate = range.gate(); + let lo = F::from(x.value().get_lower_32() as u64); + let hi = F::from((x.value().get_lower_64() >> 32) & ((1u64 << 32) - 1)); + let assigned_lo = ctx.load_witness(lo); + let assigned_hi = ctx.load_witness(hi); + range.range_check(ctx, assigned_lo, 32); + let composed = + gate.mul_add(ctx, assigned_hi, QuantumCell::Constant(F::from(1u64 << 32)), assigned_lo); + ctx.constrain_equal(x, &composed); + assigned_lo +} + +fn ch<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x: &SpreadU32<'a, F>, + y: &SpreadU32<'a, F>, + z: &SpreadU32<'a, F>, +) -> Result, Error> { + let (x_lo, x_hi) = *x; + let (y_lo, y_hi) = *y; + let (z_lo, z_hi) = *z; + let range = spread_chip.range(); + let gate = range.gate(); + let p_lo = gate.add(ctx, QuantumCell::Existing(x_lo), QuantumCell::Existing(y_lo)); + let p_hi = gate.add(ctx, QuantumCell::Existing(x_hi), QuantumCell::Existing(y_hi)); + const MASK_EVEN_32: u64 = 0x55555555; + let x_neg_lo = gate.neg(ctx, QuantumCell::Existing(x_lo)); + let x_neg_hi = gate.neg(ctx, QuantumCell::Existing(x_hi)); + let q_lo = three_add( + ctx, + gate, + QuantumCell::Constant(F::from(MASK_EVEN_32)), + QuantumCell::Existing(x_neg_lo), + QuantumCell::Existing(z_lo), + ); + let q_hi = three_add( + ctx, + gate, + QuantumCell::Constant(F::from(MASK_EVEN_32)), + QuantumCell::Existing(x_neg_hi), + QuantumCell::Existing(z_hi), + ); + let (p_lo_even, p_lo_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &p_lo)?; + let (p_hi_even, p_hi_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &p_hi)?; + let (q_lo_even, q_lo_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &q_lo)?; + let (q_hi_even, q_hi_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &q_hi)?; + { + let even_spread = spread_chip.spread(ctx, &p_lo_even)?; + let odd_spread = spread_chip.spread(ctx, &p_lo_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &p_lo); + } + { + let even_spread = spread_chip.spread(ctx, &p_hi_even)?; + let odd_spread = spread_chip.spread(ctx, &p_hi_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &p_hi); + } + { + let even_spread = spread_chip.spread(ctx, &q_lo_even)?; + let odd_spread = spread_chip.spread(ctx, &q_lo_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &q_lo); + } + { + let even_spread = spread_chip.spread(ctx, &q_hi_even)?; + let odd_spread = spread_chip.spread(ctx, &q_hi_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &q_hi); + } + let out_lo = gate.add(ctx, QuantumCell::Existing(p_lo_odd), QuantumCell::Existing(q_lo_odd)); + let out_hi = gate.add(ctx, QuantumCell::Existing(p_hi_odd), QuantumCell::Existing(q_hi_odd)); + let out = gate.mul_add( + ctx, + QuantumCell::Existing(out_hi), + QuantumCell::Constant(F::from(1u64 << 16)), + QuantumCell::Existing(out_lo), + ); + Ok(out) +} + +fn maj<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x: &SpreadU32<'a, F>, + y: &SpreadU32<'a, F>, + z: &SpreadU32<'a, F>, +) -> Result, Error> { + let (x_lo, x_hi) = *x; + let (y_lo, y_hi) = *y; + let (z_lo, z_hi) = *z; + let range = spread_chip.range(); + let gate = range.gate(); + let m_lo = three_add( + ctx, + range.gate(), + QuantumCell::Existing(x_lo), + QuantumCell::Existing(y_lo), + QuantumCell::Existing(z_lo), + ); + let m_hi = three_add( + ctx, + range.gate(), + QuantumCell::Existing(x_hi), + QuantumCell::Existing(y_hi), + QuantumCell::Existing(z_hi), + ); + let (m_lo_even, m_lo_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &m_lo)?; + let (m_hi_even, m_hi_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &m_hi)?; + { + let even_spread = spread_chip.spread(ctx, &m_lo_even)?; + let odd_spread = spread_chip.spread(ctx, &m_lo_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &m_lo); + } + { + let even_spread = spread_chip.spread(ctx, &m_hi_even)?; + let odd_spread = spread_chip.spread(ctx, &m_hi_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &m_hi); + } + let m = gate.mul_add( + ctx, + QuantumCell::Existing(m_hi_odd), + QuantumCell::Constant(F::from(1u64 << 16)), + QuantumCell::Existing(m_lo_odd), + ); + Ok(m) +} + +fn three_add<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + gate: &impl GateInstructions, + x: QuantumCell, + y: QuantumCell, + z: QuantumCell, +) -> AssignedValue { + let add1 = gate.add(ctx, x, y); + gate.add(ctx, QuantumCell::Existing(add1), z) +} + +fn sigma_upper0<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x_spread: &SpreadU32, +) -> Result, Error> { + const STARTS: [usize; 4] = [0, 2, 13, 22]; + const ENDS: [usize; 4] = [2, 13, 22, 32]; + const PADDINGS: [usize; 4] = [6, 5, 7, 6]; + let coeffs = [ + F::from((1u64 << 60) + (1u64 << 38) + (1u64 << 20)), + F::from((1u64 << 0) + (1u64 << 42) + (1u64 << 24)), + F::from((1u64 << 22) + (1u64 << 0) + (1u64 << 46)), + F::from((1u64 << 40) + (1u64 << 18) + (1u64 << 0)), + ]; + sigma_generic(ctx, spread_chip, x_spread, &STARTS, &ENDS, &PADDINGS, &coeffs) +} + +fn sigma_upper1<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x_spread: &SpreadU32, +) -> Result, Error> { + const STARTS: [usize; 4] = [0, 6, 11, 25]; + const ENDS: [usize; 4] = [6, 11, 25, 32]; + const PADDINGS: [usize; 4] = [2, 3, 2, 1]; + let coeffs = [ + F::from((1u64 << 52) + (1u64 << 42) + (1u64 << 14)), + F::from((1u64 << 0) + (1u64 << 54) + (1u64 << 26)), + F::from((1u64 << 10) + (1u64 << 0) + (1u64 << 36)), + F::from((1u64 << 38) + (1u64 << 28) + (1u64 << 0)), + ]; + sigma_generic(ctx, spread_chip, x_spread, &STARTS, &ENDS, &PADDINGS, &coeffs) +} + +fn sigma_lower0<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x_spread: &SpreadU32, +) -> Result, Error> { + const STARTS: [usize; 4] = [0, 3, 7, 18]; + const ENDS: [usize; 4] = [3, 7, 18, 32]; + const PADDINGS: [usize; 4] = [5, 4, 5, 2]; + let coeffs = [ + F::from((1u64 << 50) + (1u64 << 28)), + F::from((1u64 << 0) + (1u64 << 56) + (1u64 << 34)), + F::from((1u64 << 8) + (1u64 << 0) + (1u64 << 42)), + F::from((1u64 << 30) + (1u64 << 22) + (1u64 << 0)), + ]; + sigma_generic(ctx, spread_chip, x_spread, &STARTS, &ENDS, &PADDINGS, &coeffs) +} + +fn sigma_lower1<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x_spread: &SpreadU32, +) -> Result, Error> { + const STARTS: [usize; 4] = [0, 10, 17, 19]; + const ENDS: [usize; 4] = [10, 17, 19, 32]; + const PADDINGS: [usize; 4] = [6, 1, 6, 3]; + let coeffs = [ + F::from((1u64 << 30) + (1u64 << 26)), + F::from((1u64 << 0) + (1u64 << 50) + (1u64 << 46)), + F::from((1u64 << 14) + (1u64 << 0) + (1u64 << 60)), + F::from((1u64 << 18) + (1u64 << 4) + (1u64 << 0)), + ]; + sigma_generic(ctx, spread_chip, x_spread, &STARTS, &ENDS, &PADDINGS, &coeffs) +} + +#[allow(clippy::too_many_arguments)] +fn sigma_generic<'a, 'b: 'a, F: BigPrimeField>( + ctx: &mut Context, + spread_chip: &SpreadChip<'a, F>, + x_spread: &SpreadU32, + starts: &[usize; 4], + ends: &[usize; 4], + paddings: &[usize; 4], + coeffs: &[F; 4], +) -> Result, Error> { + let range = spread_chip.range(); + let gate = range.gate(); + // let x_spread = spread_config.spread(ctx, range, x)?; + let bits_val = { + let (lo, hi) = (x_spread.0.value(), x_spread.1.value()); + let mut bits = fe_to_bits_le(lo, 32); + bits.append(&mut fe_to_bits_le(hi, 32)); + bits + }; + let mut assign_bits = |bits: &Vec, start: usize, end: usize, _padding: usize| { + let fe_val: F = { + let mut bits = bits[2 * start..2 * end].to_vec(); + bits.extend_from_slice(&vec![false; 64 - bits.len()]); + bits_le_to_fe(&bits) + }; + + // let assigned_spread = spread_config.spread(ctx, range, &assigned_dense)?; + // let result: Result, Error> = Ok(assigned_spread); + ctx.load_witness(fe_val) + }; + let assigned_a = assign_bits(&bits_val, starts[0], ends[0], paddings[0]); + let assigned_b = assign_bits(&bits_val, starts[1], ends[1], paddings[1]); + let assigned_c = assign_bits(&bits_val, starts[2], ends[2], paddings[2]); + let assigned_d = assign_bits(&bits_val, starts[3], ends[3], paddings[3]); + { + let mut sum = assigned_a; + sum = gate.mul_add( + ctx, + assigned_b, + QuantumCell::Constant(F::from(1 << (2 * starts[1]))), + sum, + ); + sum = gate.mul_add( + ctx, + assigned_c, + QuantumCell::Constant(F::from(1 << (2 * starts[2]))), + sum, + ); + sum = gate.mul_add( + ctx, + assigned_d, + QuantumCell::Constant(F::from(1 << (2 * starts[3]))), + sum, + ); + let x_composed = + gate.mul_add(ctx, x_spread.1, QuantumCell::Constant(F::from(1 << 32)), x_spread.0); + ctx.constrain_equal(&x_composed, &sum); + } + + let r_spread = { + // let a_coeff = F::from(1u64 << 60 + 1u64 << 38 + 1u64 << 20); + // let b_coeff = F::from(1u64 << 0 + 1u64 << 42 + 1u64 << 24); + // let c_coeff = F::from(1u64 << 22 + 1u64 << 0 + 1u64 << 46); + // let d_coeff = F::from(1u64 << 40 + 1u64 << 18 + 1u64 << 0); + let mut sum = ctx.load_zero(); + // let assigned_a_spread = spread_config.spread(ctx, range, &assigned_a)?; + // let assigned_b_spread = spread_config.spread(ctx, range, &assigned_b)?; + // let assigned_c_spread = spread_config.spread(ctx, range, &assigned_c)?; + // let assigned_d_spread = spread_config.spread(ctx, range, &assigned_d)?; + sum = gate.mul_add(ctx, QuantumCell::Constant(coeffs[0]), assigned_a, sum); + sum = gate.mul_add(ctx, QuantumCell::Constant(coeffs[1]), assigned_b, sum); + sum = gate.mul_add(ctx, QuantumCell::Constant(coeffs[2]), assigned_c, sum); + sum = gate.mul_add(ctx, QuantumCell::Constant(coeffs[3]), assigned_d, sum); + sum + }; + let (r_lo, r_hi) = { + let lo = F::from(r_spread.value().get_lower_32() as u64); + let hi = F::from(((r_spread.value().get_lower_64() >> 32) & ((1u64 << 32) - 1)) as u64); + let assigned_lo = ctx.load_witness(lo); + let assigned_hi = ctx.load_witness(hi); + range.range_check(ctx, assigned_lo, 32); + range.range_check(ctx, assigned_hi, 32); + let composed = gate.mul_add( + ctx, + QuantumCell::Existing(assigned_hi), + QuantumCell::Constant(F::from(1u64 << 32)), + QuantumCell::Existing(assigned_lo), + ); + ctx.constrain_equal(&r_spread, &composed); + (assigned_lo, assigned_hi) + }; + + let (r_lo_even, r_lo_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &r_lo)?; + let (r_hi_even, r_hi_odd) = spread_chip.decompose_even_and_odd_unchecked(ctx, &r_hi)?; + + { + let even_spread = spread_chip.spread(ctx, &r_lo_even)?; + let odd_spread = spread_chip.spread(ctx, &r_lo_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &r_lo); + } + + { + let even_spread = spread_chip.spread(ctx, &r_hi_even)?; + let odd_spread = spread_chip.spread(ctx, &r_hi_odd)?; + let sum = gate.mul_add( + ctx, + QuantumCell::Constant(F::from(2)), + QuantumCell::Existing(odd_spread), + QuantumCell::Existing(even_spread), + ); + ctx.constrain_equal(&sum, &r_hi); + } + + let r = gate.mul_add( + ctx, + QuantumCell::Existing(r_hi_even), + QuantumCell::Constant(F::from(1 << 16)), + QuantumCell::Existing(r_lo_even), + ); + + Ok(r) +} diff --git a/halo2-ecc/src/secp256k1/sha256/mod.rs b/halo2-ecc/src/secp256k1/sha256/mod.rs new file mode 100644 index 00000000..a74119ae --- /dev/null +++ b/halo2-ecc/src/secp256k1/sha256/mod.rs @@ -0,0 +1,209 @@ +use halo2_base::{ + gates::{GateInstructions, RangeChip, RangeInstructions}, + halo2_proofs::plonk::Error, + utils::BigPrimeField, + AssignedValue, Context, QuantumCell, +}; +use itertools::Itertools; + +use self::compression::{sha256_compression, INIT_STATE}; + +use self::spread::SpreadChip; + +mod compression; +mod spread; + +#[derive(Debug, Clone)] +pub struct Sha256Chip<'a, F: BigPrimeField> { + spread: SpreadChip<'a, F>, +} + +impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { + const BLOCK_SIZE: usize = 64; + const DIGEST_SIZE: usize = 32; + + pub fn new(range: &'a RangeChip) -> Self { + // Spread chip requires 16 % lookup_bits == 0 so we set it to either 8 or 16 based on circuit degree. + let lookup_bits = if range.lookup_bits() > 8 { 16 } else { 8 }; + + Self { spread: SpreadChip::new(range, lookup_bits) } + } + + fn digest_varlen( + &self, + ctx: &mut Context, + input: impl IntoIterator>, + max_len: usize, + ) -> Result>, Error> { + let max_processed_bytes = { + let mut max_bytes = max_len + 9; + let remainder = max_bytes % 64; + if remainder != 0 { + max_bytes += 64 - remainder; + } + max_bytes + }; + + let mut assigned_input_bytes = input + .into_iter() + .map(|cell| match cell { + QuantumCell::Existing(v) => v, + QuantumCell::Witness(v) => ctx.load_witness(v), + QuantumCell::Constant(v) => ctx.load_constant(v), + _ => unreachable!(), + }) + .collect_vec(); + + let input_byte_size = assigned_input_bytes.len(); + let input_byte_size_with_9 = input_byte_size + 9; + let range = self.spread.range(); + let gate = &range.gate; + + assert!(input_byte_size <= max_len); + + let one_round_size = Self::BLOCK_SIZE; + + let num_round = if input_byte_size_with_9 % one_round_size == 0 { + input_byte_size_with_9 / one_round_size + } else { + input_byte_size_with_9 / one_round_size + 1 + }; + let padded_size = one_round_size * num_round; + let zero_padding_byte_size = padded_size - input_byte_size_with_9; + + let mut assign_byte = |byte: u8| ctx.load_witness(F::from(byte as u64)); + + assigned_input_bytes.push(assign_byte(0x80)); + + for _ in 0..zero_padding_byte_size { + assigned_input_bytes.push(assign_byte(0u8)); + } + + let mut input_len_bytes = [0; 8]; + let le_size_bytes = (8 * input_byte_size).to_le_bytes(); + input_len_bytes[0..le_size_bytes.len()].copy_from_slice(&le_size_bytes); + for byte in input_len_bytes.iter().rev() { + assigned_input_bytes.push(assign_byte(*byte)); + } + + assert_eq!(assigned_input_bytes.len(), num_round * one_round_size); + + let assigned_num_round = ctx.load_witness(F::from(num_round as u64)); + + // compute an initial state from the precomputed_input. + let last_state = INIT_STATE; + + let mut assigned_last_state_vec = vec![last_state + .iter() + .map(|state| ctx.load_witness(F::from(*state as u64))) + .collect_vec()]; + + let mut num_processed_input = 0; + while num_processed_input < max_processed_bytes { + let assigned_input_word_at_round = + &assigned_input_bytes[num_processed_input..num_processed_input + one_round_size]; + let new_assigned_hs_out = sha256_compression( + ctx, + &self.spread, + assigned_input_word_at_round, + assigned_last_state_vec.last().unwrap(), + )?; + + assigned_last_state_vec.push(new_assigned_hs_out); + num_processed_input += one_round_size; + } + + let zero = ctx.load_zero(); + let mut output_h_out = vec![zero; 8]; + for (n_round, assigned_state) in assigned_last_state_vec.into_iter().enumerate() { + let selector = gate.is_equal( + ctx, + QuantumCell::Constant(F::from(n_round as u64)), + assigned_num_round, + ); + for i in 0..8 { + output_h_out[i] = gate.select(ctx, assigned_state[i], output_h_out[i], selector); + } + } + let output_digest_bytes = output_h_out + .into_iter() + .flat_map(|assigned_word| { + let be_bytes = assigned_word.value().get_lower_32().to_be_bytes().to_vec(); + let assigned_bytes = (0..4) + .map(|idx| { + let assigned = ctx.load_witness(F::from(be_bytes[idx] as u64)); + range.range_check(ctx, assigned, 8); + assigned + }) + .collect_vec(); + let mut sum = ctx.load_zero(); + for (idx, assigned_byte) in assigned_bytes.iter().copied().enumerate() { + sum = gate.mul_add( + ctx, + assigned_byte, + QuantumCell::Constant(F::from(1u64 << (24 - 8 * idx))), + sum, + ); + } + ctx.constrain_equal(&assigned_word, &sum); + assigned_bytes + }) + .collect_vec(); + + Ok(output_digest_bytes) + } + + pub fn digest( + &self, + ctx: &mut Context, + input: impl IntoIterator>, + ) -> Result>, Error> { + let input = input.into_iter().collect_vec(); + let input_len = input.len(); + self.digest_varlen(ctx, input, input_len) + } +} + +#[cfg(test)] +mod test { + use halo2_base::{ + gates::RangeInstructions, halo2_proofs::halo2curves::grumpkin::Fq as Fr, + utils::testing::base_test, QuantumCell, + }; + use itertools::Itertools; + use sha2::{Digest, Sha256}; + + use super::Sha256Chip; + + #[test] + fn test_sha256() { + let preimage = b"hello world"; + + let mut hasher = Sha256::new(); + hasher.update(preimage); + let result = hasher.finalize(); + + base_test().k(14).lookup_bits(13).expect_satisfied(true).run(|ctx, range| { + let preimage_assigned = preimage + .iter() + .map(|byte| QuantumCell::Existing(ctx.load_witness(Fr::from(*byte as u64)))) + .collect_vec(); + + let result_assinged = result + .iter() + .map(|byte| { + let assigned = ctx.load_witness(Fr::from(*byte as u64)); + range.range_check(ctx, assigned, 8); + assigned + }) + .collect_vec(); + + let sha256_chip = Sha256Chip::new(range); + let digest = sha256_chip.digest(ctx, preimage_assigned).unwrap(); + + for (assigned, expected) in digest.iter().zip(result_assinged.iter()) { + ctx.constrain_equal(assigned, expected); + } + }) + } +} diff --git a/halo2-ecc/src/secp256k1/sha256/spread.rs b/halo2-ecc/src/secp256k1/sha256/spread.rs new file mode 100644 index 00000000..50eb824e --- /dev/null +++ b/halo2-ecc/src/secp256k1/sha256/spread.rs @@ -0,0 +1,101 @@ +use halo2_base::{ + gates::{GateInstructions, RangeChip, RangeInstructions}, + halo2_proofs::plonk::Error, + utils::{decompose, BigPrimeField}, + AssignedValue, Context, QuantumCell, +}; +use itertools::Itertools; + +use crate::secp256k1::util::{bits_le_to_fe, bits_le_to_fe_assigned, fe_to_bits_le}; + +#[derive(Debug, Clone)] +pub struct SpreadChip<'a, F: BigPrimeField> { + lookup_bits: usize, + range: &'a RangeChip, +} + +impl<'a, F: BigPrimeField> SpreadChip<'a, F> { + pub fn new(range: &'a RangeChip, lookup_bits: usize) -> Self { + debug_assert_eq!(16 % lookup_bits, 0); + + Self { range, lookup_bits } + } + pub fn spread( + &self, + ctx: &mut Context, + dense: &AssignedValue, + ) -> Result, Error> { + let gate = self.range.gate(); + let limb_bits = self.lookup_bits; + let num_limbs = 16 / limb_bits; + let limbs = decompose(dense.value(), num_limbs, limb_bits); + let assigned_limbs = ctx.assign_witnesses(limbs); + { + let mut limbs_sum = ctx.load_zero(); + for (idx, limb) in assigned_limbs.iter().copied().enumerate() { + limbs_sum = gate.mul_add( + ctx, + QuantumCell::Existing(limb), + QuantumCell::Constant(F::from(1 << (limb_bits * idx))), + QuantumCell::Existing(limbs_sum), + ); + } + ctx.constrain_equal(&limbs_sum, dense); + } + let mut assigned_spread = ctx.load_zero(); + for (idx, limb) in assigned_limbs.iter().enumerate() { + let spread_limb = self.spread_limb(ctx, limb)?; + assigned_spread = gate.mul_add( + ctx, + QuantumCell::Existing(spread_limb), + QuantumCell::Constant(F::from(1 << (2 * limb_bits * idx))), + QuantumCell::Existing(assigned_spread), + ); + } + Ok(assigned_spread) + } + + pub fn decompose_even_and_odd_unchecked( + &self, + ctx: &mut Context, + spread: &AssignedValue, + ) -> Result<(AssignedValue, AssignedValue), Error> { + let bits = fe_to_bits_le(spread.value(), 32); + let even_bits = (0..bits.len() / 2).map(|idx| bits[2 * idx]).collect_vec(); + let odd_bits = (0..bits.len() / 2).map(|idx| bits[2 * idx + 1]).collect_vec(); + let (even_val, odd_val) = (bits_le_to_fe(&even_bits), bits_le_to_fe(&odd_bits)); + let even_assigned = ctx.load_witness(even_val); + let odd_assigned = ctx.load_witness(odd_val); + self.range.range_check(ctx, even_assigned, 16); + self.range.range_check(ctx, odd_assigned, 16); + Ok((even_assigned, odd_assigned)) + } + + fn spread_limb( + &self, + ctx: &mut Context, + limb: &AssignedValue, + ) -> Result, Error> { + let range = self.range; + + let limb_bits = fe_to_bits_le(limb.value(), 32); + let assigned_limb_bits = + limb_bits.iter().map(|bit| ctx.load_constant(F::from(*bit))).collect_vec(); + + let limb_sum = bits_le_to_fe_assigned(ctx, range, &assigned_limb_bits)?; + ctx.constrain_equal(&limb_sum, limb); + + let mut assigned_spread_bits = vec![ctx.load_zero(); limb_bits.len() * 2]; + for i in 0..assigned_limb_bits.len() { + assigned_spread_bits[2 * i] = assigned_limb_bits[i]; + } + + let assigned_spread = bits_le_to_fe_assigned(ctx, range, &assigned_spread_bits)?; + + Ok(assigned_spread) + } + + pub fn range(&self) -> &RangeChip { + self.range + } +} diff --git a/halo2-ecc/src/secp256k1/util.rs b/halo2-ecc/src/secp256k1/util.rs new file mode 100644 index 00000000..2e8e723b --- /dev/null +++ b/halo2-ecc/src/secp256k1/util.rs @@ -0,0 +1,50 @@ +use halo2_base::{ + gates::{GateInstructions, RangeChip, RangeInstructions}, + halo2_proofs::plonk::Error, + utils::{biguint_to_fe, fe_to_biguint, BigPrimeField}, + AssignedValue, Context, QuantumCell, +}; +use itertools::Itertools; +use num_bigint::BigUint; + +pub fn fe_to_bits_le(val: &F, size: usize) -> Vec { + let val_bytes = fe_to_biguint(val).to_bytes_le(); + let mut bits = + val_bytes.iter().flat_map(|byte| (0..8).map(move |i| ((byte >> i) & 1) == 1)).collect_vec(); + bits.extend_from_slice(&vec![false; size - bits.len()]); + bits +} + +pub fn bits_le_to_fe(bits: &[bool]) -> F { + let bytes = bits + .chunks(8) + .map(|bits| { + let mut byte = 0u8; + for idx in 0..8 { + if bits[idx] { + byte += 1 << idx; + } + } + byte + }) + .collect_vec(); + biguint_to_fe(&BigUint::from_bytes_le(&bytes)) +} + +pub fn bits_le_to_fe_assigned( + ctx: &mut Context, + range: &RangeChip, + bits: &[AssignedValue], +) -> Result, Error> { + let gate = range.gate(); + let mut sum = ctx.load_zero(); + for (idx, bit) in bits.iter().enumerate() { + sum = gate.mul_add( + ctx, + QuantumCell::Existing(*bit), + QuantumCell::Constant(F::from(1 << idx)), + QuantumCell::Existing(sum), + ); + } + Ok(sum) +} From b2e2cde221b4c373da551a9657056d685ab610b2 Mon Sep 17 00:00:00 2001 From: shryasss Date: Tue, 6 Feb 2024 08:34:10 +0530 Subject: [PATCH 02/24] feat: hash to field --- .../hash_to_curve/expand_message_xmd.rs | 2 +- .../secp256k1/hash_to_curve/hash_to_field.rs | 59 +++++++++++++++++++ .../secp256k1/hash_to_curve/map_to_curve.rs | 0 halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 4 +- halo2-ecc/src/secp256k1/mod.rs | 5 +- 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index ab73b90a..03f1fcf8 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -112,7 +112,7 @@ fn str_xor( xor } -fn expand_message_xmd( +pub fn expand_message_xmd( ctx: &mut Context, range: &RangeChip, sha256_chip: &Sha256Chip, diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs new file mode 100644 index 00000000..73d359df --- /dev/null +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -0,0 +1,59 @@ +use halo2_base::{ + gates::{ GateInstructions, RangeChip, RangeInstructions }, + utils::BigPrimeField, + AssignedValue, + Context, + QuantumCell, +}; + +use crate::{ bigint::{ ProperCrtUint, ProperUint }, secp256k1::sha256::Sha256Chip }; + +use super::expand_message_xmd::expand_message_xmd; + +pub fn hash_to_field( + ctx: &mut Context, + range: &RangeChip, + sha256_chip: &Sha256Chip, + msg_bytes: &[AssignedValue] +) -> (ProperCrtUint, ProperCrtUint) { + let expanded_msg_bytes = expand_message_xmd(ctx, range, sha256_chip, msg_bytes); + + let u0 = bytes_to_registers(ctx, range, &expanded_msg_bytes[0..48]); + let u1 = bytes_to_registers(ctx, range, &expanded_msg_bytes[48..96]); + + (u0, u1) +} + +fn bytes_to_registers( + ctx: &mut Context, + range: &RangeChip, + bytes: &[AssignedValue] +) -> ProperCrtUint { + assert_eq!(bytes.len(), 48); + + let gate = range.gate(); + + let mut assigned_int = Vec::>::new(); + for (_, chunk) in bytes.chunks(8).enumerate() { + let mut assigned_u64 = ctx.load_zero(); + for (j, byte) in chunk.iter().enumerate() { + assigned_u64 = gate.mul_add( + ctx, + QuantumCell::Existing(*byte), + QuantumCell::Constant(F::from(1 << (8 * j))), + QuantumCell::Existing(assigned_u64) + ); + } + assigned_int.push(assigned_u64); + } + + // TODO: calculate, out = assigned_int (mod SECP_MODULUS) + let int_bases = Vec::::with_capacity(assigned_int.len()); + for i in 0..assigned_int.len() { + int_bases.push(F::from(1 << (64 * i))); + } + + let assigned_int = ProperUint(assigned_int).into_crt(ctx, gate, value, limb_bases, limb_bits); + + assigned_int +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs new file mode 100644 index 00000000..e69de29b diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index dad19c76..2845df8d 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -1,3 +1,5 @@ +pub mod util; pub mod constants; pub mod expand_message_xmd; -pub mod util; +pub mod hash_to_field; +pub mod map_to_curve; diff --git a/halo2-ecc/src/secp256k1/mod.rs b/halo2-ecc/src/secp256k1/mod.rs index 38970d20..15c5b8a4 100644 --- a/halo2-ecc/src/secp256k1/mod.rs +++ b/halo2-ecc/src/secp256k1/mod.rs @@ -1,4 +1,4 @@ -use crate::halo2_proofs::halo2curves::secp256k1::{Fp, Fq}; +use crate::halo2_proofs::halo2curves::secp256k1::{ Fp, Fq }; use crate::ecc; use crate::fields::fp; @@ -7,6 +7,9 @@ pub type FpChip<'range, F> = fp::FpChip<'range, F, Fp>; pub type FqChip<'range, F> = fp::FpChip<'range, F, Fq>; pub type Secp256k1Chip<'chip, F> = ecc::EccChip<'chip, F, FpChip<'chip, F>>; pub const SECP_B: u64 = 7; +pub const SECP_MODULUS: [u64; 4] = [ + 18446744069414583343u64, 18446744073709551615u64, 18446744073709551615u64, 18446744073709551615u64, +]; pub mod hash_to_curve; pub mod sha256; From 8741785a4045442a549c1cebbc1bc7785b56bc90 Mon Sep 17 00:00:00 2001 From: shryasss Date: Tue, 6 Feb 2024 17:45:56 +0530 Subject: [PATCH 03/24] feat(wip): hash_to_curve impl --- .../src/secp256k1/hash_to_curve/constants.rs | 206 +++++++++++- .../secp256k1/hash_to_curve/hash_to_field.rs | 4 +- .../src/secp256k1/hash_to_curve/iso_map.rs | 302 ++++++++++++++++++ .../secp256k1/hash_to_curve/map_to_curve.rs | 237 ++++++++++++++ halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 62 ++++ 5 files changed, 804 insertions(+), 7 deletions(-) create mode 100644 halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index eec0dfe5..9e621428 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -1,4 +1,6 @@ -use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; +use halo2_base::{ utils::BigPrimeField, AssignedValue, Context }; + +use crate::bigint::ProperCrtUint; pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { let zero = ctx.load_zero(); @@ -13,9 +15,203 @@ pub(crate) fn get_lib_str(ctx: &mut Context) -> Vec(ctx: &mut Context) -> Vec> { let dst_prime = [ - 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, - 99, 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, - 87, 85, 95, 82, 79, 95, 49, + 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, 99, + 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, 87, + 85, 95, 82, 79, 95, 49, + ]; + dst_prime + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>() +} + +pub(crate) fn get_Z(ctx: &mut Context) -> ProperCrtUint { + let z = [ + 18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615, + ]; + let z = z + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_A(ctx: &mut Context) -> ProperCrtUint { + let a = [4635408806871057715, 16813014259472469597, 11568152433342665330, 4577682160469023452]; + let a = a + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_B(ctx: &mut Context) -> ProperCrtUint { + let a = [1771, 0, 0, 0]; + let a = a + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_C1(ctx: &mut Context) -> ProperCrtUint { + let c2 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994]; + let c2 = c2 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_C2(ctx: &mut Context) -> ProperCrtUint { + let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804]; + let c2 = c2 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_1_0(ctx: &mut Context) -> ProperCrtUint { + let k_1_0 = [ + 10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008, + ]; + let k_1_0 = k_1_0 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_1_1(ctx: &mut Context) -> ProperCrtUint { + let k_1_1 = [ + 16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237, + ]; + let k_1_1 = k_1_1 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_1_2(ctx: &mut Context) -> ProperCrtUint { + let k_1_2 = [ + 5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894, + ]; + let k_1_2 = k_1_2 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_1_3(ctx: &mut Context) -> ProperCrtUint { + let k_1_3 = [ + 10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008, + ]; + let k_1_3 = k_1_3 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_2_0(ctx: &mut Context) -> ProperCrtUint { + let k_2_0 = [ + 11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418, + ]; + let k_2_0 = k_2_0 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_2_1(ctx: &mut Context) -> ProperCrtUint { + let k_2_1 = [ + 14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821, + ]; + let k_2_1 = k_2_1 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_3_0(ctx: &mut Context) -> ProperCrtUint { + let k_3_0 = [ + 11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071, + ]; + let k_3_0 = k_3_0 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_3_1(ctx: &mut Context) -> ProperCrtUint { + let k_3_1 = [ + 16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615, + ]; + let k_3_1 = k_3_1 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_3_2(ctx: &mut Context) -> ProperCrtUint { + let k_3_2 = [ + 12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947, + ]; + let k_3_2 = k_3_2 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_3_3(ctx: &mut Context) -> ProperCrtUint { + let k_3_3 = [ + 9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669, + ]; + let k_3_3 = k_3_3 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_4_0(ctx: &mut Context) -> ProperCrtUint { + let k_4_0 = [ + 18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615, + ]; + let k_4_0 = k_4_0 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_4_1(ctx: &mut Context) -> ProperCrtUint { + let k_4_1 = [ + 16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023, + ]; + let k_4_1 = k_4_1 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); +} + +pub(crate) fn get_k_4_2(ctx: &mut Context) -> ProperCrtUint { + let k_4_2 = [ + 12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116, ]; - dst_prime.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>() + let k_4_2 = k_4_2 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index 73d359df..e5fd9cb1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -48,12 +48,12 @@ fn bytes_to_registers( } // TODO: calculate, out = assigned_int (mod SECP_MODULUS) - let int_bases = Vec::::with_capacity(assigned_int.len()); + let mut int_bases = Vec::::with_capacity(assigned_int.len()); for i in 0..assigned_int.len() { int_bases.push(F::from(1 << (64 * i))); } - let assigned_int = ProperUint(assigned_int).into_crt(ctx, gate, value, limb_bases, limb_bits); + let assigned_int = ProperUint(assigned_int); assigned_int } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs new file mode 100644 index 00000000..a41d58ea --- /dev/null +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -0,0 +1,302 @@ +use halo2_base::{ + gates::{ RangeChip, RangeInstructions }, + utils::{ log2_ceil, BigPrimeField }, + Context, +}; + +use crate::bigint::{ add_no_carry, big_is_equal, mul_no_carry, ProperCrtUint }; + +use super::constants::{ + get_k_1_0, + get_k_1_1, + get_k_1_2, + get_k_1_3, + get_k_2_0, + get_k_2_1, + get_k_3_0, + get_k_3_1, + get_k_3_2, + get_k_3_3, + get_k_4_0, + get_k_4_1, + get_k_4_2, +}; + +fn x_num( + ctx: &mut Context, + range: &RangeChip, + x: ProperCrtUint, + x_2: ProperCrtUint, + x_3: ProperCrtUint +) -> ProperCrtUint { + let gate = range.gate(); + + let k_1_3 = get_k_1_3(ctx); + let k_1_2 = get_k_1_2(ctx); + let k_1_1 = get_k_1_1(ctx); + let k_1_0 = get_k_1_0(ctx); + + // Step 1: a = k_(1,3) * x'^3 + let a = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + k_1_3.0.clone(), + x_3.0.clone(), + log2_ceil(x_3.limbs().len() as u64) + ) + ); + + // Step 2: b = k_(1,2) * x'^2 + + let b = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + k_1_2.0.clone(), + x_2.0.clone(), + log2_ceil(x_2.limbs().len() as u64) + ) + ); + + // Step 3: c = k_(1,1) * x' + + let c = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + k_1_1.0.clone(), + x.0.clone(), + log2_ceil(x.limbs().len() as u64) + ) + ); + + // Step 4: a + b + let a_plus_b = ProperCrtUint(add_no_carry::crt(gate, ctx, a.0, b.0)); + + // Step 5: a + b + c + let a_plus_b_plus_c = ProperCrtUint(add_no_carry::crt(gate, ctx, a_plus_b.0, c.0)); + + // Step 6: a + b + c + k_1_0 + let a_plus_b_plus_c_plus_k_1_0 = ProperCrtUint( + add_no_carry::crt(gate, ctx, a_plus_b_plus_c.0, k_1_0.0) + ); + + a_plus_b_plus_c_plus_k_1_0 +} + +fn x_den( + ctx: &mut Context, + range: &RangeChip, + x: ProperCrtUint, + x_2: ProperCrtUint +) -> ProperCrtUint { + let k_2_0 = get_k_2_0(ctx); + let k_2_1 = get_k_2_1(ctx); + + // Step 1: a = x_2 + k_2_0 + let a = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, x_2.0, k_2_0.0)); + + // Step 2: b = x * k_2_1 + let b = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + x.0.clone(), + k_2_1.0.clone(), + log2_ceil(x.limbs().len() as u64) + ) + ); + + // Step 3: c = a + b + let c = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a.0, b.0)); + + c +} + +fn y_num( + ctx: &mut Context, + range: &RangeChip, + x: ProperCrtUint, + x_2: ProperCrtUint, + x_3: ProperCrtUint +) -> ProperCrtUint { + let k_3_3 = get_k_3_3(ctx); + let k_3_2 = get_k_3_2(ctx); + let k_3_1 = get_k_3_1(ctx); + let k_3_0 = get_k_3_0(ctx); + + // Step 1: a = k_3_3 * x_3 + let a = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + k_3_3.0.clone(), + x_3.0.clone(), + log2_ceil(x_3.limbs().len() as u64) + ) + ); + + // Step 2: b = k_3_2 * x_2 + let b = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + k_3_2.0.clone(), + x_2.0.clone(), + log2_ceil(x_2.limbs().len() as u64) + ) + ); + + // Step 3: c = k_3_1 * x + let c = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + k_3_1.0.clone(), + x.0.clone(), + log2_ceil(x.limbs().len() as u64) + ) + ); + + // Step 4: a + b + let a_plus_b = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a.0, b.0)); + + // Step 5: a + b + c + let a_plus_b_plus_c = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a_plus_b.0, c.0)); + + // Step 6: a + b + c + k_3_0 + let a_plus_b_plus_c_plus_k_3_0 = ProperCrtUint( + add_no_carry::crt(range.gate(), ctx, a_plus_b_plus_c.0, k_3_0.0) + ); + + a_plus_b_plus_c_plus_k_3_0 +} + +fn y_den( + ctx: &mut Context, + range: &RangeChip, + x: ProperCrtUint, + x_2: ProperCrtUint, + x_3: ProperCrtUint +) -> ProperCrtUint { + let k_4_0 = get_k_4_0(ctx); + let k_4_1 = get_k_4_1(ctx); + let k_4_2 = get_k_4_2(ctx); + + // Step 1: a = x_3 + k_4_0 + let a = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, x_3.0, k_4_0.0)); + + // Step 2: b = k_4_2 * x_2 + let b = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + k_4_2.0.clone(), + x_2.0.clone(), + log2_ceil(x_2.limbs().len() as u64) + ) + ); + + // Step 3: c = k_4_1 * x + let c = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + k_4_1.0.clone(), + x.0.clone(), + log2_ceil(x.limbs().len() as u64) + ) + ); + + // Step 4: a + b + let a_plus_b = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a.0, b.0)); + + // Step 5: a + b + c + let a_plus_b_plus_c = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a_plus_b.0, c.0)); + + a_plus_b_plus_c +} + +pub fn iso_map( + ctx: &mut Context, + range: &RangeChip, + x: ProperCrtUint, + y: ProperCrtUint, + x_mapped: ProperCrtUint, + y_mapped: ProperCrtUint +) { + let gate = range.gate(); + let one = ctx.load_constant(F::ONE); + + // Step 1: calculate x^2 + let x_2 = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + x.0.clone(), + x.0.clone(), + log2_ceil(x.limbs().len() as u64) + ) + ); + + // Step 2: calculate x^3 + let x_3 = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + x.0.clone(), + x_2.0.clone(), + log2_ceil(x_2.limbs().len() as u64) + ) + ); + + // Step 3: calculate x_num + let x_num = x_num(ctx, range, x, x_2, x_3); + + // Step 4: calculate x_den + let x_den = x_den(ctx, range, x, x_2); + + // Step 5: calculate y_num + let y_num = y_num(ctx, range, x, x_2, x_3); + + // Step 6: calculate y_den + let y_den = y_den(ctx, range, x, x_2, x_3); + + // Step 7: x_mapped * x_den === x_num + let x_check = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + x_mapped.0.clone(), + x_den.0.clone(), + log2_ceil(x_den.limbs().len() as u64) + ) + ); + + // Step 8: y_mapped = y' * y_num / y_den + // y_mapped * y_den === y' * y_num + let y_check = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + y_mapped.0.clone(), + y_den.0.clone(), + log2_ceil(y_den.limbs().len() as u64) + ) + ); + + let y_check_2 = ProperCrtUint( + mul_no_carry::crt( + range.gate(), + ctx, + y.0.clone(), + y_num.0.clone(), + log2_ceil(y_num.limbs().len() as u64) + ) + ); + + // Ensure that the provided x_mapped and y_mapped values are correct + let check1 = big_is_equal::assign(gate, ctx, x_check, x_num); + ctx.constrain_equal(&check1, &one); + let check_2 = big_is_equal::assign(gate, ctx, y_check, y_check_2); + ctx.constrain_equal(&check_2, &one); +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index e69de29b..9dcf0b21 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -0,0 +1,237 @@ +use halo2_base::{ + gates::{ GateInstructions, RangeChip, RangeInstructions }, + utils::{ log2_ceil, BigPrimeField }, + AssignedValue, + Context, +}; +use num_bigint::BigInt; + +use crate::{ + bigint::{ + add_no_carry, + big_is_equal, + big_is_even::positive, + mul_no_carry, + negative, + select, + CRTInteger, + OverflowInteger, + ProperCrtUint, + }, + secp256k1::hash_to_curve::{ + constants::{ get_A, get_B, get_C1, get_C2, get_Z }, + iso_map::iso_map, + }, +}; + +fn inv_0() { + // TODO +} + +fn sgn_0( + ctx: &mut Context, + range: &RangeChip, + num: OverflowInteger +) -> AssignedValue { + positive(range, ctx, num.clone(), num.max_limb_bits) +} + +fn xy2_selector( + ctx: &mut Context, + range: &RangeChip, + gx1: ProperCrtUint, + gx1_sqrt: ProperCrtUint, + gx2: ProperCrtUint, + gx2_sqrt: ProperCrtUint, + x1: ProperCrtUint, + x2: ProperCrtUint +) -> (ProperCrtUint, ProperCrtUint) { + let gate = range.gate(); + let one = ctx.load_constant(F::ONE); + + let sq_gx1_sqrt = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + gx1_sqrt.0.clone(), + gx1_sqrt.0.clone(), + log2_ceil(gx1_sqrt.limbs().len() as u64) + ) + ); + + let sq_gx2_sqrt = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + gx2_sqrt.0.clone(), + gx2_sqrt.0.clone(), + log2_ceil(gx2_sqrt.limbs().len() as u64) + ) + ); + + let s1 = big_is_equal::assign(gate, ctx, sq_gx1_sqrt, gx1.clone()); + let s2 = big_is_equal::assign(gate, ctx, sq_gx2_sqrt, gx2.clone()); + + let _one = gate.add(ctx, s1, s2); + ctx.constrain_equal(&_one, &one); + + let x = ProperCrtUint(select::crt(gate, ctx, x1.0, x2.0, s1)); + let y2 = ProperCrtUint(select::crt(gate, ctx, gx1.0, gx2.0, s1)); + + (x, y2) +} + +pub fn map_to_curve( + ctx: &mut Context, + range: &RangeChip, + u: ProperCrtUint, + gx1_sqrt: ProperCrtUint, + gx2_sqrt: ProperCrtUint, + y_pos: ProperCrtUint, + x_mapped: ProperCrtUint, + y_mapped: ProperCrtUint +) -> (ProperCrtUint, ProperCrtUint) { + let gate = range.gate(); + let zero = ctx.load_zero(); + let one = ctx.load_constant(F::ONE); + let crt_one = ProperCrtUint( + CRTInteger::new(OverflowInteger::new(vec![one], 64), one, BigInt::from(1u64)) + ); + + // Step 1: tv1 = Z * u^2 + let u_sq = ProperCrtUint( + mul_no_carry::crt(gate, ctx, u.0.clone(), u.0.clone(), log2_ceil(u.limbs().len() as u64)) + ); + let z = get_Z(ctx); + let tv1 = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + z.0.clone(), + u_sq.0.clone(), + log2_ceil(u_sq.limbs().len() as u64) + ) + ); + + // Step 2: tv2 = tv1^2 + let tv2 = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + tv1.0.clone(), + tv1.0.clone(), + log2_ceil(tv1.limbs().len() as u64) + ) + ); + + // Step 3: x1 = tv1 + tv2 + let x1 = ProperCrtUint(add_no_carry::crt(gate, ctx, tv1.0, tv2.0)); + + // Step 4: x1 = inv0(x1) + // TODO + + // Step 5: e1 = x1 == 0 + let e1 = gate.is_equal(ctx, x1.0.native, zero); + + // Step 6: x1 = x1 + 1 + let x1 = ProperCrtUint(add_no_carry::crt(gate, ctx, x1.0, crt_one.0)); + + // Step 7: x1 = e1 ? c2 : x1 + let c2 = get_C2(ctx); + let x1 = ProperCrtUint(select::crt(gate, ctx, x1.0, c2.0, e1)); + + // Step 8: x1 = x1 * c1 # x1 = (-B / A) * (1 + (1 / (Z^2 * u^4 + Z * u^2))) + let c1 = get_C1(ctx); + assert_eq!(c1.limbs().len(), x1.limbs().len()); + let x1 = ProperCrtUint( + mul_no_carry::crt(gate, ctx, x1.0.clone(), c1.0.clone(), log2_ceil(c1.limbs().len() as u64)) + ); + + // Step 9: gx1 = x1^2 + let gx1 = ProperCrtUint( + mul_no_carry::crt(gate, ctx, x1.0.clone(), x1.0.clone(), log2_ceil(x1.limbs().len() as u64)) + ); + + // Step 10: gx1 = gx1 + A + let a = get_A(ctx); + let gx1 = ProperCrtUint(add_no_carry::crt(gate, ctx, gx1.0, a.0)); + + // Step 11: gx1 = gx1 * x1 + let gx1 = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + gx1.0.clone(), + x1.0.clone(), + log2_ceil(x1.limbs().len() as u64) + ) + ); + + // Step 12: gx1 = gx1 + B # gx1 = g(x1) = x1^3 + A * x1 + B + let b = get_B(ctx); + let gx1 = ProperCrtUint(add_no_carry::crt(gate, ctx, gx1.0, b.0)); + + // Step 13: x2 = tv1 * x1 # x2 = Z * u^2 * x1 + let x2 = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + tv1.0.clone(), + x1.0.clone(), + log2_ceil(x1.limbs().len() as u64) + ) + ); + + // Step 14: tv2 = tv1 * tv2 + let tv2 = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + tv1.0.clone(), + tv2.0.clone(), + log2_ceil(tv1.limbs().len() as u64) + ) + ); + + // Step 15: gx2 = gx1 * tv2 # gx2 = (Z * u^2)^3 * gx1 + let gx2 = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + gx1.0.clone(), + tv2.0.clone(), + log2_ceil(tv2.limbs().len() as u64) + ) + ); + + // Steps 16-18: + // e2 = is_square(gx1) + // x = CMOV(x2, x1, e2) # If is_square(gx1), x = x1, else x = x2 + // y2 = CMOV(gx2, gx1, e2) # If is_square(gx1), y2 = gx1, else y2 = gx2 + let (x, y2) = xy2_selector(ctx, range, gx1, gx1_sqrt, gx2, gx2_sqrt, x1, x2); + + // Step 19: y = sqrt(y2) + let y_pos_sq = ProperCrtUint( + mul_no_carry::crt( + gate, + ctx, + y_pos.0.clone(), + y_pos.0.clone(), + log2_ceil(y_pos.limbs().len() as u64) + ) + ); + ctx.constrain_equal(&big_is_equal::assign(gate, ctx, y_pos_sq, y2.clone()), &one); + + // Step 20: e3 = sgn0(u) == sgn0(y) # Fix sign of y + let sgn_u = sgn_0(ctx, range, u.0.truncation); + let sgn_y = sgn_0(ctx, range, y_pos.0.truncation); + let e3 = gate.is_equal(ctx, sgn_u, sgn_y); + + // Step 21: y = e3 ? y : -y + let neg_y_pos = negative::assign(gate, ctx, y_pos.0.truncation); + let y = ProperCrtUint(select::crt(gate, ctx, y_pos.0, neg_y_pos, e3)); + + iso_map(ctx, range, x, y, x_mapped, y_mapped); + + (x_mapped, y_mapped) +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index 2845df8d..010dbe42 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -1,5 +1,67 @@ +use halo2_base::{ gates::RangeChip, utils::BigPrimeField, AssignedValue, Context }; + +use crate::{ bigint::ProperCrtUint, ecc::EcPoint, fields::FieldChip }; + +use self::hash_to_field::hash_to_field; + +use super::sha256::Sha256Chip; + pub mod util; pub mod constants; pub mod expand_message_xmd; pub mod hash_to_field; pub mod map_to_curve; +pub mod iso_map; + +pub fn hash_to_curve>( + ctx: &mut Context, + range: &RangeChip, + ecc_chip: &FC, + sha256_chip: &Sha256Chip, + msg_bytes: &[AssignedValue], + q0_gx1_sqrt: ProperCrtUint, + q0_gx2_sqrt: ProperCrtUint, + q0_y_pos: ProperCrtUint, + q0_x_mapped: ProperCrtUint, + q0_y_mapped: ProperCrtUint, + q1_gx1_sqrt: ProperCrtUint, + q1_gx2_sqrt: ProperCrtUint, + q1_y_pos: ProperCrtUint, + q1_x_mapped: ProperCrtUint, + q1_y_mapped: ProperCrtUint +) -> EcPoint> { + // Step 1: u = hash_to_field(msg) + let (u0, u1) = hash_to_field(ctx, range, sha256_chip, msg_bytes); + + // Step 2: Q0 = map_to_curve(u[0]) + let (q0_x, q0_y2) = map_to_curve::map_to_curve( + ctx, + range, + u0, + q0_gx1_sqrt, + q0_gx2_sqrt, + q0_y_pos, + q0_x_mapped, + q0_y_mapped + ); + + // Step 3: Q1 = map_to_curve(u[1]) + let (q1_x, q1_y2) = map_to_curve::map_to_curve( + ctx, + range, + u1, + q0_gx1_sqrt, + q0_gx2_sqrt, + q0_y_pos, + q0_x_mapped, + q0_y_mapped + ); + + // Step 4: return A + B + let q0 = EcPoint::>::new(q0_x_mapped, q0_y_mapped); + let q1 = EcPoint::>::new(q1_x_mapped, q1_y_mapped); + + let point_add = ecc_chip.add_no_carry(ctx, q0, q1); + + point_add +} From 9e0a842280fab99e4dd283efd06e0ddd94bed01c Mon Sep 17 00:00:00 2001 From: shryasss Date: Wed, 7 Feb 2024 17:33:44 +0530 Subject: [PATCH 04/24] feat: hash_to_curve impl done --- halo2-ecc/Cargo.toml | 2 +- .../src/secp256k1/hash_to_curve/constants.rs | 324 +++++++++--------- .../hash_to_curve/expand_message_xmd.rs | 10 +- .../secp256k1/hash_to_curve/hash_to_field.rs | 39 +-- .../src/secp256k1/hash_to_curve/iso_map.rs | 269 +++++---------- .../secp256k1/hash_to_curve/map_to_curve.rs | 213 ++++-------- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 41 +-- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 64 +++- halo2-ecc/src/secp256k1/mod.rs | 5 +- 9 files changed, 406 insertions(+), 561 deletions(-) diff --git a/halo2-ecc/Cargo.toml b/halo2-ecc/Cargo.toml index 0ae1610a..98ff56e5 100644 --- a/halo2-ecc/Cargo.toml +++ b/halo2-ecc/Cargo.toml @@ -13,7 +13,7 @@ rust-version = "1.73.0" itertools = "0.11" num-bigint = { version = "0.4", features = ["rand"] } num-integer = "0.1" -num-traits = "0.2" +num-traits = "0.2.17" rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } rand = "0.8" rand_chacha = "0.3.1" diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index 9e621428..f381b003 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -1,7 +1,9 @@ -use halo2_base::{ utils::BigPrimeField, AssignedValue, Context }; +use halo2_base::{gates::RangeChip, utils::BigPrimeField, AssignedValue, Context}; use crate::bigint::ProperCrtUint; +use super::util::limbs_le_to_bigint; + pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { let zero = ctx.load_zero(); vec![zero; 64] @@ -15,203 +17,203 @@ pub(crate) fn get_lib_str(ctx: &mut Context) -> Vec(ctx: &mut Context) -> Vec> { let dst_prime = [ - 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, 99, - 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, 87, - 85, 95, 82, 79, 95, 49, + 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, + 99, 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, + 87, 85, 95, 82, 79, 95, 49, ]; - dst_prime - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>() + dst_prime.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>() } -pub(crate) fn get_Z(ctx: &mut Context) -> ProperCrtUint { - let z = [ - 18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615, - ]; - let z = z - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_Z( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let z = + [18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615]; + let z = z.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, z.as_slice(), 64) } -pub(crate) fn get_A(ctx: &mut Context) -> ProperCrtUint { +pub(crate) fn get_A( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { let a = [4635408806871057715, 16813014259472469597, 11568152433342665330, 4577682160469023452]; - let a = a - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); + let a = a.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, a.as_slice(), 64) } -pub(crate) fn get_B(ctx: &mut Context) -> ProperCrtUint { - let a = [1771, 0, 0, 0]; - let a = a - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_B( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let b = [1771, 0, 0, 0]; + let b = b.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, b.as_slice(), 64) } -pub(crate) fn get_C1(ctx: &mut Context) -> ProperCrtUint { - let c2 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994]; - let c2 = c2 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_C1( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let c1 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994]; + let c1 = c1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, c1.as_slice(), 64) } -pub(crate) fn get_C2(ctx: &mut Context) -> ProperCrtUint { +pub(crate) fn get_C2( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804]; - let c2 = c2 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); + let c2 = c2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, c2.as_slice(), 64) } -pub(crate) fn get_k_1_0(ctx: &mut Context) -> ProperCrtUint { - let k_1_0 = [ - 10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008, - ]; - let k_1_0 = k_1_0 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_1_0( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_1_0 = + [10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008]; + let k_1_0 = k_1_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_1_0.as_slice(), 64) } -pub(crate) fn get_k_1_1(ctx: &mut Context) -> ProperCrtUint { - let k_1_1 = [ - 16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237, - ]; - let k_1_1 = k_1_1 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_1_1( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_1_1 = + [16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237]; + let k_1_1 = k_1_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_1_1.as_slice(), 64) } -pub(crate) fn get_k_1_2(ctx: &mut Context) -> ProperCrtUint { - let k_1_2 = [ - 5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894, - ]; - let k_1_2 = k_1_2 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_1_2( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_1_2 = + [5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894]; + let k_1_2 = k_1_2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_1_2.as_slice(), 64) } -pub(crate) fn get_k_1_3(ctx: &mut Context) -> ProperCrtUint { - let k_1_3 = [ - 10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008, - ]; - let k_1_3 = k_1_3 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_1_3( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_1_3 = + [10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008]; + let k_1_3 = k_1_3.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_1_3.as_slice(), 64) } -pub(crate) fn get_k_2_0(ctx: &mut Context) -> ProperCrtUint { - let k_2_0 = [ - 11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418, - ]; - let k_2_0 = k_2_0 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_2_0( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_2_0 = + [11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418]; + let k_2_0 = k_2_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_2_0.as_slice(), 64) } -pub(crate) fn get_k_2_1(ctx: &mut Context) -> ProperCrtUint { - let k_2_1 = [ - 14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821, - ]; - let k_2_1 = k_2_1 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_2_1( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_2_1 = + [14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821]; + let k_2_1 = k_2_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_2_1.as_slice(), 64) } -pub(crate) fn get_k_3_0(ctx: &mut Context) -> ProperCrtUint { - let k_3_0 = [ - 11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071, - ]; - let k_3_0 = k_3_0 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_3_0( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_3_0 = + [11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071]; + let k_3_0 = k_3_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_3_0.as_slice(), 64) } -pub(crate) fn get_k_3_1(ctx: &mut Context) -> ProperCrtUint { - let k_3_1 = [ - 16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615, - ]; - let k_3_1 = k_3_1 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_3_1( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_3_1 = + [16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615]; + let k_3_1 = k_3_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_3_1.as_slice(), 64) } -pub(crate) fn get_k_3_2(ctx: &mut Context) -> ProperCrtUint { - let k_3_2 = [ - 12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947, - ]; - let k_3_2 = k_3_2 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_3_2( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_3_2 = + [12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947]; + let k_3_2 = k_3_2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_3_2.as_slice(), 64) } -pub(crate) fn get_k_3_3(ctx: &mut Context) -> ProperCrtUint { - let k_3_3 = [ - 9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669, - ]; - let k_3_3 = k_3_3 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_3_3( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_3_3 = + [9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669]; + let k_3_3 = k_3_3.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_3_3.as_slice(), 64) } -pub(crate) fn get_k_4_0(ctx: &mut Context) -> ProperCrtUint { - let k_4_0 = [ - 18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615, - ]; - let k_4_0 = k_4_0 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_4_0( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_4_0 = + [18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615]; + let k_4_0 = k_4_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_4_0.as_slice(), 64) } -pub(crate) fn get_k_4_1(ctx: &mut Context) -> ProperCrtUint { - let k_4_1 = [ - 16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023, - ]; - let k_4_1 = k_4_1 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_4_1( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_4_1 = + [16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023]; + let k_4_1 = k_4_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_4_1.as_slice(), 64) } -pub(crate) fn get_k_4_2(ctx: &mut Context) -> ProperCrtUint { - let k_4_2 = [ - 12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116, - ]; - let k_4_2 = k_4_2 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>(); +pub(crate) fn get_k_4_2( + ctx: &mut Context, + range: &RangeChip, +) -> ProperCrtUint { + let k_4_2 = + [12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116]; + let k_4_2 = k_4_2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + + limbs_le_to_bigint(ctx, range, k_4_2.as_slice(), 64) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index 03f1fcf8..f3ba0e0f 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -62,11 +62,7 @@ fn hash_bi( let b0_bits = bytes_to_bits_le_assigned(ctx, range, b0_bytes); let bi_minus_one_bits = bytes_to_bits_le_assigned(ctx, range, bi_minus_one_bytes); - let mut xor_bits = Vec::>::new(); - for (bo_bit, bi_minus_one_bit) in b0_bits.iter().zip(bi_minus_one_bits.iter()) { - let res = range.gate().xor(ctx, *bo_bit, *bi_minus_one_bit); - xor_bits.push(res); - } + let xor_bits = str_xor(ctx, range, &b0_bits, &bi_minus_one_bits); let xor_bytes = bits_le_to_bytes_assigned(ctx, range, &xor_bits); let bi_bytes = hash_b(ctx, sha256_chip, b_idx_byte, &xor_bytes); @@ -74,9 +70,9 @@ fn hash_bi( bi_bytes } -fn hash_b<'a, F: BigPrimeField>( +fn hash_b( ctx: &mut Context, - sha256_chip: &Sha256Chip<'a, F>, + sha256_chip: &Sha256Chip<'_, F>, b_idx_byte: &AssignedValue, b_bytes: &Vec>, ) -> Vec> { diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index e5fd9cb1..5ca1e2e4 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -1,36 +1,39 @@ use halo2_base::{ - gates::{ GateInstructions, RangeChip, RangeInstructions }, + gates::{GateInstructions, RangeInstructions}, utils::BigPrimeField, - AssignedValue, - Context, - QuantumCell, + AssignedValue, Context, QuantumCell, }; -use crate::{ bigint::{ ProperCrtUint, ProperUint }, secp256k1::sha256::Sha256Chip }; +use crate::{ + bigint::ProperCrtUint, + fields::FieldChip, + secp256k1::{hash_to_curve::util::limbs_le_to_bigint, sha256::Sha256Chip, FpChip}, +}; use super::expand_message_xmd::expand_message_xmd; pub fn hash_to_field( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, sha256_chip: &Sha256Chip, - msg_bytes: &[AssignedValue] + msg_bytes: &[AssignedValue], ) -> (ProperCrtUint, ProperCrtUint) { - let expanded_msg_bytes = expand_message_xmd(ctx, range, sha256_chip, msg_bytes); + let expanded_msg_bytes = expand_message_xmd(ctx, fp_chip.range, sha256_chip, msg_bytes); - let u0 = bytes_to_registers(ctx, range, &expanded_msg_bytes[0..48]); - let u1 = bytes_to_registers(ctx, range, &expanded_msg_bytes[48..96]); + let u0 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[0..48]); + let u1 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[48..96]); (u0, u1) } fn bytes_to_registers( ctx: &mut Context, - range: &RangeChip, - bytes: &[AssignedValue] + fp_chip: &FpChip<'_, F>, + bytes: &[AssignedValue], ) -> ProperCrtUint { assert_eq!(bytes.len(), 48); + let range = fp_chip.range; let gate = range.gate(); let mut assigned_int = Vec::>::new(); @@ -41,19 +44,13 @@ fn bytes_to_registers( ctx, QuantumCell::Existing(*byte), QuantumCell::Constant(F::from(1 << (8 * j))), - QuantumCell::Existing(assigned_u64) + QuantumCell::Existing(assigned_u64), ); } assigned_int.push(assigned_u64); } - // TODO: calculate, out = assigned_int (mod SECP_MODULUS) - let mut int_bases = Vec::::with_capacity(assigned_int.len()); - for i in 0..assigned_int.len() { - int_bases.push(F::from(1 << (64 * i))); - } - - let assigned_int = ProperUint(assigned_int); + let int = limbs_le_to_bigint(ctx, range, &assigned_int, 64); - assigned_int + fp_chip.carry_mod(ctx, int.into()) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs index a41d58ea..bf0e27ff 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -1,302 +1,187 @@ -use halo2_base::{ - gates::{ RangeChip, RangeInstructions }, - utils::{ log2_ceil, BigPrimeField }, - Context, -}; +use halo2_base::{utils::BigPrimeField, Context}; -use crate::bigint::{ add_no_carry, big_is_equal, mul_no_carry, ProperCrtUint }; +use crate::{bigint::ProperCrtUint, fields::FieldChip, secp256k1::FpChip}; use super::constants::{ - get_k_1_0, - get_k_1_1, - get_k_1_2, - get_k_1_3, - get_k_2_0, - get_k_2_1, - get_k_3_0, - get_k_3_1, - get_k_3_2, - get_k_3_3, - get_k_4_0, - get_k_4_1, - get_k_4_2, + get_k_1_0, get_k_1_1, get_k_1_2, get_k_1_3, get_k_2_0, get_k_2_1, get_k_3_0, get_k_3_1, + get_k_3_2, get_k_3_3, get_k_4_0, get_k_4_1, get_k_4_2, }; fn x_num( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint + x_3: ProperCrtUint, ) -> ProperCrtUint { - let gate = range.gate(); + let range = fp_chip.range(); - let k_1_3 = get_k_1_3(ctx); - let k_1_2 = get_k_1_2(ctx); - let k_1_1 = get_k_1_1(ctx); - let k_1_0 = get_k_1_0(ctx); + let k_1_3 = get_k_1_3(ctx, range); + let k_1_2 = get_k_1_2(ctx, range); + let k_1_1 = get_k_1_1(ctx, range); + let k_1_0 = get_k_1_0(ctx, range); // Step 1: a = k_(1,3) * x'^3 - let a = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - k_1_3.0.clone(), - x_3.0.clone(), - log2_ceil(x_3.limbs().len() as u64) - ) - ); + let a = fp_chip.mul(ctx, k_1_3, x_3); // Step 2: b = k_(1,2) * x'^2 + - let b = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - k_1_2.0.clone(), - x_2.0.clone(), - log2_ceil(x_2.limbs().len() as u64) - ) - ); + let b = fp_chip.mul(ctx, k_1_2, x_2); // Step 3: c = k_(1,1) * x' + - let c = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - k_1_1.0.clone(), - x.0.clone(), - log2_ceil(x.limbs().len() as u64) - ) - ); + let c = fp_chip.mul(ctx, k_1_1, x); // Step 4: a + b - let a_plus_b = ProperCrtUint(add_no_carry::crt(gate, ctx, a.0, b.0)); + let a_plus_b = fp_chip.add_no_carry(ctx, a, b); + let a_plus_b = fp_chip.carry_mod(ctx, a_plus_b); // Step 5: a + b + c - let a_plus_b_plus_c = ProperCrtUint(add_no_carry::crt(gate, ctx, a_plus_b.0, c.0)); + let a_plus_b_plus_c = fp_chip.add_no_carry(ctx, a_plus_b, c); + let a_plus_b_plus_c = fp_chip.carry_mod(ctx, a_plus_b_plus_c); // Step 6: a + b + c + k_1_0 - let a_plus_b_plus_c_plus_k_1_0 = ProperCrtUint( - add_no_carry::crt(gate, ctx, a_plus_b_plus_c.0, k_1_0.0) - ); + let a_plus_b_plus_c_plus_k_1_0 = fp_chip.add_no_carry(ctx, a_plus_b_plus_c, k_1_0); + let a_plus_b_plus_c_plus_k_1_0 = fp_chip.carry_mod(ctx, a_plus_b_plus_c_plus_k_1_0); a_plus_b_plus_c_plus_k_1_0 } fn x_den( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, x: ProperCrtUint, - x_2: ProperCrtUint + x_2: ProperCrtUint, ) -> ProperCrtUint { - let k_2_0 = get_k_2_0(ctx); - let k_2_1 = get_k_2_1(ctx); + let range = fp_chip.range(); + + let k_2_0 = get_k_2_0(ctx, range); + let k_2_1 = get_k_2_1(ctx, range); // Step 1: a = x_2 + k_2_0 - let a = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, x_2.0, k_2_0.0)); + let a = fp_chip.add_no_carry(ctx, x_2, k_2_0); + let a = fp_chip.carry_mod(ctx, a); // Step 2: b = x * k_2_1 - let b = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - x.0.clone(), - k_2_1.0.clone(), - log2_ceil(x.limbs().len() as u64) - ) - ); + let b = fp_chip.mul(ctx, x, k_2_1); // Step 3: c = a + b - let c = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a.0, b.0)); + let c = fp_chip.add_no_carry(ctx, a, b); + let c = fp_chip.carry_mod(ctx, c); c } fn y_num( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint + x_3: ProperCrtUint, ) -> ProperCrtUint { - let k_3_3 = get_k_3_3(ctx); - let k_3_2 = get_k_3_2(ctx); - let k_3_1 = get_k_3_1(ctx); - let k_3_0 = get_k_3_0(ctx); + let range = fp_chip.range(); + + let k_3_3 = get_k_3_3(ctx, range); + let k_3_2 = get_k_3_2(ctx, range); + let k_3_1 = get_k_3_1(ctx, range); + let k_3_0 = get_k_3_0(ctx, range); // Step 1: a = k_3_3 * x_3 - let a = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - k_3_3.0.clone(), - x_3.0.clone(), - log2_ceil(x_3.limbs().len() as u64) - ) - ); + let a = fp_chip.mul(ctx, k_3_3, x_3); // Step 2: b = k_3_2 * x_2 - let b = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - k_3_2.0.clone(), - x_2.0.clone(), - log2_ceil(x_2.limbs().len() as u64) - ) - ); + let b = fp_chip.mul(ctx, k_3_2, x_2); // Step 3: c = k_3_1 * x - let c = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - k_3_1.0.clone(), - x.0.clone(), - log2_ceil(x.limbs().len() as u64) - ) - ); + let c = fp_chip.mul(ctx, k_3_1, x); // Step 4: a + b - let a_plus_b = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a.0, b.0)); + let a_plus_b = fp_chip.add_no_carry(ctx, a, b); + let a_plus_b = fp_chip.carry_mod(ctx, a_plus_b); // Step 5: a + b + c - let a_plus_b_plus_c = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a_plus_b.0, c.0)); + let a_plus_b_plus_c = fp_chip.add_no_carry(ctx, a_plus_b, c); + let a_plus_b_plus_c = fp_chip.carry_mod(ctx, a_plus_b_plus_c); // Step 6: a + b + c + k_3_0 - let a_plus_b_plus_c_plus_k_3_0 = ProperCrtUint( - add_no_carry::crt(range.gate(), ctx, a_plus_b_plus_c.0, k_3_0.0) - ); + let a_plus_b_plus_c_plus_k_3_0 = fp_chip.add_no_carry(ctx, a_plus_b_plus_c, k_3_0); + let a_plus_b_plus_c_plus_k_3_0 = fp_chip.carry_mod(ctx, a_plus_b_plus_c_plus_k_3_0); a_plus_b_plus_c_plus_k_3_0 } fn y_den( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint + x_3: ProperCrtUint, ) -> ProperCrtUint { - let k_4_0 = get_k_4_0(ctx); - let k_4_1 = get_k_4_1(ctx); - let k_4_2 = get_k_4_2(ctx); + let range = fp_chip.range(); + + let k_4_0 = get_k_4_0(ctx, range); + let k_4_1 = get_k_4_1(ctx, range); + let k_4_2 = get_k_4_2(ctx, range); // Step 1: a = x_3 + k_4_0 - let a = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, x_3.0, k_4_0.0)); + let a = fp_chip.add_no_carry(ctx, x_3, k_4_0); + let a = fp_chip.carry_mod(ctx, a); // Step 2: b = k_4_2 * x_2 - let b = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - k_4_2.0.clone(), - x_2.0.clone(), - log2_ceil(x_2.limbs().len() as u64) - ) - ); + let b = fp_chip.mul(ctx, k_4_2, x_2); // Step 3: c = k_4_1 * x - let c = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - k_4_1.0.clone(), - x.0.clone(), - log2_ceil(x.limbs().len() as u64) - ) - ); + let c = fp_chip.mul(ctx, k_4_1, x); // Step 4: a + b - let a_plus_b = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a.0, b.0)); + let a_plus_b = fp_chip.add_no_carry(ctx, a, b); + let a_plus_b = fp_chip.carry_mod(ctx, a_plus_b); // Step 5: a + b + c - let a_plus_b_plus_c = ProperCrtUint(add_no_carry::crt(range.gate(), ctx, a_plus_b.0, c.0)); + let a_plus_b_plus_c = fp_chip.add_no_carry(ctx, a_plus_b, c); + let a_plus_b_plus_c = fp_chip.carry_mod(ctx, a_plus_b_plus_c); a_plus_b_plus_c } pub fn iso_map( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, x: ProperCrtUint, y: ProperCrtUint, x_mapped: ProperCrtUint, - y_mapped: ProperCrtUint + y_mapped: ProperCrtUint, ) { - let gate = range.gate(); let one = ctx.load_constant(F::ONE); // Step 1: calculate x^2 - let x_2 = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - x.0.clone(), - x.0.clone(), - log2_ceil(x.limbs().len() as u64) - ) - ); + let x_2 = fp_chip.mul(ctx, x.clone(), x.clone()); // Step 2: calculate x^3 - let x_3 = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - x.0.clone(), - x_2.0.clone(), - log2_ceil(x_2.limbs().len() as u64) - ) - ); + let x_3 = fp_chip.mul(ctx, x.clone(), x_2.clone()); // Step 3: calculate x_num - let x_num = x_num(ctx, range, x, x_2, x_3); + let x_num = x_num(ctx, fp_chip, x.clone(), x_2.clone(), x_3.clone()); // Step 4: calculate x_den - let x_den = x_den(ctx, range, x, x_2); + let x_den = x_den(ctx, fp_chip, x.clone(), x_2.clone()); // Step 5: calculate y_num - let y_num = y_num(ctx, range, x, x_2, x_3); + let y_num = y_num(ctx, fp_chip, x.clone(), x_2.clone(), x_3.clone()); // Step 6: calculate y_den - let y_den = y_den(ctx, range, x, x_2, x_3); + let y_den = y_den(ctx, fp_chip, x, x_2, x_3); // Step 7: x_mapped * x_den === x_num - let x_check = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - x_mapped.0.clone(), - x_den.0.clone(), - log2_ceil(x_den.limbs().len() as u64) - ) - ); + let x_check = fp_chip.mul(ctx, x_mapped, x_den); // Step 8: y_mapped = y' * y_num / y_den // y_mapped * y_den === y' * y_num - let y_check = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - y_mapped.0.clone(), - y_den.0.clone(), - log2_ceil(y_den.limbs().len() as u64) - ) - ); - - let y_check_2 = ProperCrtUint( - mul_no_carry::crt( - range.gate(), - ctx, - y.0.clone(), - y_num.0.clone(), - log2_ceil(y_num.limbs().len() as u64) - ) - ); + let y_check = fp_chip.mul(ctx, y_mapped, y_den); + + let y_check_2 = fp_chip.mul(ctx, y, y_num); // Ensure that the provided x_mapped and y_mapped values are correct - let check1 = big_is_equal::assign(gate, ctx, x_check, x_num); + let check1 = fp_chip.is_equal(ctx, x_check, x_num); ctx.constrain_equal(&check1, &one); - let check_2 = big_is_equal::assign(gate, ctx, y_check, y_check_2); + let check_2 = fp_chip.is_equal(ctx, y_check, y_check_2); ctx.constrain_equal(&check_2, &one); } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 9dcf0b21..a40d33f9 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -1,237 +1,142 @@ use halo2_base::{ - gates::{ GateInstructions, RangeChip, RangeInstructions }, - utils::{ log2_ceil, BigPrimeField }, - AssignedValue, + gates::{GateInstructions, RangeInstructions}, + utils::BigPrimeField, Context, }; -use num_bigint::BigInt; +use num_bigint::BigUint; use crate::{ - bigint::{ - add_no_carry, - big_is_equal, - big_is_even::positive, - mul_no_carry, - negative, - select, - CRTInteger, - OverflowInteger, - ProperCrtUint, - }, - secp256k1::hash_to_curve::{ - constants::{ get_A, get_B, get_C1, get_C2, get_Z }, - iso_map::iso_map, + bigint::ProperCrtUint, + fields::{FieldChip, Selectable}, + secp256k1::{ + hash_to_curve::{ + constants::{get_A, get_B, get_C1, get_C2, get_Z}, + iso_map::iso_map, + }, + FpChip, }, }; -fn inv_0() { - // TODO -} - -fn sgn_0( - ctx: &mut Context, - range: &RangeChip, - num: OverflowInteger -) -> AssignedValue { - positive(range, ctx, num.clone(), num.max_limb_bits) -} +use super::util::mod_inverse; fn xy2_selector( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, gx1: ProperCrtUint, gx1_sqrt: ProperCrtUint, gx2: ProperCrtUint, gx2_sqrt: ProperCrtUint, x1: ProperCrtUint, - x2: ProperCrtUint + x2: ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { - let gate = range.gate(); + let gate = fp_chip.range.gate(); let one = ctx.load_constant(F::ONE); - let sq_gx1_sqrt = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - gx1_sqrt.0.clone(), - gx1_sqrt.0.clone(), - log2_ceil(gx1_sqrt.limbs().len() as u64) - ) - ); - - let sq_gx2_sqrt = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - gx2_sqrt.0.clone(), - gx2_sqrt.0.clone(), - log2_ceil(gx2_sqrt.limbs().len() as u64) - ) - ); - - let s1 = big_is_equal::assign(gate, ctx, sq_gx1_sqrt, gx1.clone()); - let s2 = big_is_equal::assign(gate, ctx, sq_gx2_sqrt, gx2.clone()); + let sq_gx1_sqrt = fp_chip.mul(ctx, gx1_sqrt.clone(), gx1_sqrt); + let sq_gx2_sqrt = fp_chip.mul(ctx, gx2_sqrt.clone(), gx2_sqrt); + + let s1 = fp_chip.is_equal(ctx, sq_gx1_sqrt, gx1.clone()); + let s2 = fp_chip.is_equal(ctx, sq_gx2_sqrt, gx2.clone()); let _one = gate.add(ctx, s1, s2); ctx.constrain_equal(&_one, &one); - let x = ProperCrtUint(select::crt(gate, ctx, x1.0, x2.0, s1)); - let y2 = ProperCrtUint(select::crt(gate, ctx, gx1.0, gx2.0, s1)); + let x = fp_chip.select(ctx, x1, x2, s1); + let y2 = fp_chip.select(ctx, gx1, gx2, s1); (x, y2) } pub fn map_to_curve( ctx: &mut Context, - range: &RangeChip, + fp_chip: &FpChip<'_, F>, u: ProperCrtUint, gx1_sqrt: ProperCrtUint, gx2_sqrt: ProperCrtUint, y_pos: ProperCrtUint, x_mapped: ProperCrtUint, - y_mapped: ProperCrtUint + y_mapped: ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { + let range = fp_chip.range(); let gate = range.gate(); - let zero = ctx.load_zero(); + let one = ctx.load_constant(F::ONE); - let crt_one = ProperCrtUint( - CRTInteger::new(OverflowInteger::new(vec![one], 64), one, BigInt::from(1u64)) - ); + + let zero_int = fp_chip.load_constant_uint(ctx, BigUint::from(0u64)); + let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); // Step 1: tv1 = Z * u^2 - let u_sq = ProperCrtUint( - mul_no_carry::crt(gate, ctx, u.0.clone(), u.0.clone(), log2_ceil(u.limbs().len() as u64)) - ); - let z = get_Z(ctx); - let tv1 = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - z.0.clone(), - u_sq.0.clone(), - log2_ceil(u_sq.limbs().len() as u64) - ) - ); + let u_sq = fp_chip.mul(ctx, u.clone(), u.clone()); + let z = get_Z(ctx, range); + let tv1 = fp_chip.mul(ctx, z, u_sq); // Step 2: tv2 = tv1^2 - let tv2 = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - tv1.0.clone(), - tv1.0.clone(), - log2_ceil(tv1.limbs().len() as u64) - ) - ); + let tv2 = fp_chip.mul(ctx, tv1.clone(), tv1.clone()); // Step 3: x1 = tv1 + tv2 - let x1 = ProperCrtUint(add_no_carry::crt(gate, ctx, tv1.0, tv2.0)); + let x1 = ProperCrtUint(fp_chip.add_no_carry(ctx, tv1.clone(), tv2.clone())); // Step 4: x1 = inv0(x1) - // TODO + let x1 = mod_inverse(ctx, fp_chip, x1); // Step 5: e1 = x1 == 0 - let e1 = gate.is_equal(ctx, x1.0.native, zero); + let e1 = fp_chip.is_equal(ctx, x1.clone(), zero_int); // Step 6: x1 = x1 + 1 - let x1 = ProperCrtUint(add_no_carry::crt(gate, ctx, x1.0, crt_one.0)); + let x1 = ProperCrtUint(fp_chip.add_no_carry(ctx, x1.clone(), one_int)); // Step 7: x1 = e1 ? c2 : x1 - let c2 = get_C2(ctx); - let x1 = ProperCrtUint(select::crt(gate, ctx, x1.0, c2.0, e1)); + let c2 = get_C2(ctx, range); + let x1 = fp_chip.select(ctx, c2, x1, e1); // Step 8: x1 = x1 * c1 # x1 = (-B / A) * (1 + (1 / (Z^2 * u^4 + Z * u^2))) - let c1 = get_C1(ctx); - assert_eq!(c1.limbs().len(), x1.limbs().len()); - let x1 = ProperCrtUint( - mul_no_carry::crt(gate, ctx, x1.0.clone(), c1.0.clone(), log2_ceil(c1.limbs().len() as u64)) - ); + let c1 = get_C1(ctx, range); + let x1 = fp_chip.mul(ctx, x1.clone(), c1); // Step 9: gx1 = x1^2 - let gx1 = ProperCrtUint( - mul_no_carry::crt(gate, ctx, x1.0.clone(), x1.0.clone(), log2_ceil(x1.limbs().len() as u64)) - ); + let gx1 = fp_chip.mul(ctx, x1.clone(), x1.clone()); // Step 10: gx1 = gx1 + A - let a = get_A(ctx); - let gx1 = ProperCrtUint(add_no_carry::crt(gate, ctx, gx1.0, a.0)); + let a = get_A(ctx, range); + let gx1 = ProperCrtUint(fp_chip.add_no_carry(ctx, gx1, a)); // Step 11: gx1 = gx1 * x1 - let gx1 = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - gx1.0.clone(), - x1.0.clone(), - log2_ceil(x1.limbs().len() as u64) - ) - ); + let gx1 = fp_chip.mul(ctx, gx1, x1.clone()); // Step 12: gx1 = gx1 + B # gx1 = g(x1) = x1^3 + A * x1 + B - let b = get_B(ctx); - let gx1 = ProperCrtUint(add_no_carry::crt(gate, ctx, gx1.0, b.0)); + let b = get_B(ctx, range); + let gx1 = ProperCrtUint(fp_chip.add_no_carry(ctx, gx1, b)); // Step 13: x2 = tv1 * x1 # x2 = Z * u^2 * x1 - let x2 = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - tv1.0.clone(), - x1.0.clone(), - log2_ceil(x1.limbs().len() as u64) - ) - ); + let x2 = fp_chip.mul(ctx, tv1.clone(), x1.clone()); // Step 14: tv2 = tv1 * tv2 - let tv2 = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - tv1.0.clone(), - tv2.0.clone(), - log2_ceil(tv1.limbs().len() as u64) - ) - ); + let tv2 = fp_chip.mul(ctx, tv1, tv2); // Step 15: gx2 = gx1 * tv2 # gx2 = (Z * u^2)^3 * gx1 - let gx2 = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - gx1.0.clone(), - tv2.0.clone(), - log2_ceil(tv2.limbs().len() as u64) - ) - ); + let gx2 = fp_chip.mul(ctx, gx1.clone(), tv2); // Steps 16-18: // e2 = is_square(gx1) // x = CMOV(x2, x1, e2) # If is_square(gx1), x = x1, else x = x2 // y2 = CMOV(gx2, gx1, e2) # If is_square(gx1), y2 = gx1, else y2 = gx2 - let (x, y2) = xy2_selector(ctx, range, gx1, gx1_sqrt, gx2, gx2_sqrt, x1, x2); + let (x, y2) = xy2_selector(ctx, fp_chip, gx1, gx1_sqrt, gx2, gx2_sqrt, x1, x2); // Step 19: y = sqrt(y2) - let y_pos_sq = ProperCrtUint( - mul_no_carry::crt( - gate, - ctx, - y_pos.0.clone(), - y_pos.0.clone(), - log2_ceil(y_pos.limbs().len() as u64) - ) - ); - ctx.constrain_equal(&big_is_equal::assign(gate, ctx, y_pos_sq, y2.clone()), &one); + let y_pos_sq = fp_chip.mul(ctx, y_pos.clone(), y_pos.clone()); + let e2 = fp_chip.is_equal(ctx, y_pos_sq, y2); + ctx.constrain_equal(&e2, &one); // Step 20: e3 = sgn0(u) == sgn0(y) # Fix sign of y - let sgn_u = sgn_0(ctx, range, u.0.truncation); - let sgn_y = sgn_0(ctx, range, y_pos.0.truncation); + let sgn_u = fp_chip.is_even(ctx, u); + let sgn_y = fp_chip.is_even(ctx, y_pos.clone()); let e3 = gate.is_equal(ctx, sgn_u, sgn_y); // Step 21: y = e3 ? y : -y - let neg_y_pos = negative::assign(gate, ctx, y_pos.0.truncation); - let y = ProperCrtUint(select::crt(gate, ctx, y_pos.0, neg_y_pos, e3)); + let neg_y_pos = fp_chip.negate(ctx, y_pos.clone()); + let y = fp_chip.select(ctx, y_pos, neg_y_pos, e3); - iso_map(ctx, range, x, y, x_mapped, y_mapped); + iso_map(ctx, fp_chip, x, y, x_mapped.clone(), y_mapped.clone()); (x_mapped, y_mapped) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index 010dbe42..75fd7269 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -1,22 +1,21 @@ -use halo2_base::{ gates::RangeChip, utils::BigPrimeField, AssignedValue, Context }; +use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; -use crate::{ bigint::ProperCrtUint, ecc::EcPoint, fields::FieldChip }; +use crate::{bigint::ProperCrtUint, ecc::EcPoint}; use self::hash_to_field::hash_to_field; -use super::sha256::Sha256Chip; +use super::{sha256::Sha256Chip, Secp256k1Chip}; -pub mod util; pub mod constants; pub mod expand_message_xmd; pub mod hash_to_field; -pub mod map_to_curve; pub mod iso_map; +pub mod map_to_curve; +pub mod util; -pub fn hash_to_curve>( +pub fn hash_to_curve( ctx: &mut Context, - range: &RangeChip, - ecc_chip: &FC, + secp256k1_chip: Secp256k1Chip<'_, F>, sha256_chip: &Sha256Chip, msg_bytes: &[AssignedValue], q0_gx1_sqrt: ProperCrtUint, @@ -28,40 +27,42 @@ pub fn hash_to_curve>( q1_gx2_sqrt: ProperCrtUint, q1_y_pos: ProperCrtUint, q1_x_mapped: ProperCrtUint, - q1_y_mapped: ProperCrtUint + q1_y_mapped: ProperCrtUint, ) -> EcPoint> { + let fp_chip = secp256k1_chip.field_chip(); + // Step 1: u = hash_to_field(msg) - let (u0, u1) = hash_to_field(ctx, range, sha256_chip, msg_bytes); + let (u0, u1) = hash_to_field(ctx, fp_chip, sha256_chip, msg_bytes); // Step 2: Q0 = map_to_curve(u[0]) let (q0_x, q0_y2) = map_to_curve::map_to_curve( ctx, - range, + fp_chip, u0, q0_gx1_sqrt, q0_gx2_sqrt, q0_y_pos, - q0_x_mapped, - q0_y_mapped + q0_x_mapped.clone(), + q0_y_mapped.clone(), ); // Step 3: Q1 = map_to_curve(u[1]) let (q1_x, q1_y2) = map_to_curve::map_to_curve( ctx, - range, + fp_chip, u1, - q0_gx1_sqrt, - q0_gx2_sqrt, - q0_y_pos, - q0_x_mapped, - q0_y_mapped + q1_gx1_sqrt, + q1_gx2_sqrt, + q1_y_pos, + q1_x_mapped.clone(), + q1_y_mapped.clone(), ); // Step 4: return A + B let q0 = EcPoint::>::new(q0_x_mapped, q0_y_mapped); let q1 = EcPoint::>::new(q1_x_mapped, q1_y_mapped); - let point_add = ecc_chip.add_no_carry(ctx, q0, q1); + let point_add = secp256k1_chip.add_unequal(ctx, q0, q1, false); point_add } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index a695307b..184756b2 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -4,8 +4,17 @@ use halo2_base::{ AssignedValue, Context, QuantumCell, }; use itertools::Itertools; +use num_bigint::BigUint; +use num_traits::Pow; -use crate::secp256k1::util::{bits_le_to_fe_assigned, fe_to_bits_le}; +use crate::{ + bigint::{ProperCrtUint, ProperUint}, + fields::FieldChip, + secp256k1::{ + util::{bits_le_to_fe_assigned, fe_to_bits_le}, + FpChip, + }, +}; pub fn byte_to_bits_le_assigned( ctx: &mut Context, @@ -51,3 +60,56 @@ pub fn bits_le_to_bytes_assigned( ) -> Vec> { bits.chunks(8).map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)).collect_vec() } + +pub fn limbs_le_to_bigint( + ctx: &mut Context, + range: &RangeChip, + limbs: &[AssignedValue], + max_limb_bits: usize, +) -> ProperCrtUint { + let native_limbs = limbs.iter().map(|limb| *limb.value()).collect_vec(); + + let mut value = BigUint::from(0u64); + let mut limb_bases = Vec::::with_capacity(native_limbs.len()); + for (idx, limb) in native_limbs.iter().enumerate() { + let limb = BigUint::from_bytes_le(limb.to_bytes_le().as_slice()); + let limb_base = BigUint::from(2u64).pow(BigUint::from(idx) * BigUint::from(max_limb_bits)); + limb_bases.push(F::from_bytes_le(limb_base.to_bytes_le().as_slice())); + let shifted_limb = limb * limb_base; + value += shifted_limb; + } + + let int = ProperUint(limbs.to_vec()).into_crt( + ctx, + range.gate(), + value, + limb_bases.as_slice(), + max_limb_bits, + ); + + int +} + +pub fn mod_inverse( + ctx: &mut Context, + fp_chip: &FpChip<'_, F>, + num: ProperCrtUint, +) -> ProperCrtUint { + let one = ctx.load_constant(F::ONE); + let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); + + let p = fp_chip.p.to_biguint().unwrap(); + let p_minus_two = p.clone() - 2u64; + + let num_native = num.value(); + let inverse_native = num_native.clone().pow(p_minus_two); + let mod_inverse_native = inverse_native % p; + assert_eq!(num_native * mod_inverse_native.clone(), BigUint::from(1u64)); + + let mod_inverse = fp_chip.load_constant_uint(ctx, mod_inverse_native); + let is_one = fp_chip.mul(ctx, num, mod_inverse.clone()); + let is_equal = fp_chip.is_equal(ctx, is_one, one_int); + ctx.constrain_equal(&is_equal, &one); + + mod_inverse +} diff --git a/halo2-ecc/src/secp256k1/mod.rs b/halo2-ecc/src/secp256k1/mod.rs index 15c5b8a4..38970d20 100644 --- a/halo2-ecc/src/secp256k1/mod.rs +++ b/halo2-ecc/src/secp256k1/mod.rs @@ -1,4 +1,4 @@ -use crate::halo2_proofs::halo2curves::secp256k1::{ Fp, Fq }; +use crate::halo2_proofs::halo2curves::secp256k1::{Fp, Fq}; use crate::ecc; use crate::fields::fp; @@ -7,9 +7,6 @@ pub type FpChip<'range, F> = fp::FpChip<'range, F, Fp>; pub type FqChip<'range, F> = fp::FpChip<'range, F, Fq>; pub type Secp256k1Chip<'chip, F> = ecc::EccChip<'chip, F, FpChip<'chip, F>>; pub const SECP_B: u64 = 7; -pub const SECP_MODULUS: [u64; 4] = [ - 18446744069414583343u64, 18446744073709551615u64, 18446744073709551615u64, 18446744073709551615u64, -]; pub mod hash_to_curve; pub mod sha256; From 58c190b7616aceb3c30a341626e02fa9be1fca61 Mon Sep 17 00:00:00 2001 From: shryasss Date: Thu, 8 Feb 2024 13:23:51 +0530 Subject: [PATCH 05/24] chore: minor changes --- .../secp256k1/hash_to_curve/expand_message_xmd.rs | 9 +++++++-- .../src/secp256k1/hash_to_curve/hash_to_field.rs | 6 +++--- halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs | 2 +- .../src/secp256k1/hash_to_curve/map_to_curve.rs | 14 +++++++++----- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 6 +++--- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 12 ++++++------ 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index f3ba0e0f..cf1530e1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -11,6 +11,10 @@ use super::{ util::{bits_le_to_bytes_assigned, bytes_to_bits_le_assigned}, }; +fn calc_msg_prime_output_length(msg_length: usize) -> usize { + msg_length + 64 + 2 + 50 + 1 +} + fn msg_prime( ctx: &mut Context, msg_bytes: &[AssignedValue], @@ -21,7 +25,8 @@ fn msg_prime( let lib_str = get_lib_str(ctx); let dst_prime = get_dst_prime(ctx); - let mut msg_prime = Vec::>::new(); + let mut msg_prime = + Vec::>::with_capacity(calc_msg_prime_output_length(msg_bytes.len())); // msg_prme = z_pad ... msg_prime.extend(z_pad); @@ -108,7 +113,7 @@ fn str_xor( xor } -pub fn expand_message_xmd( +pub(crate) fn expand_message_xmd( ctx: &mut Context, range: &RangeChip, sha256_chip: &Sha256Chip, diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index 5ca1e2e4..a3bf87c4 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -12,7 +12,7 @@ use crate::{ use super::expand_message_xmd::expand_message_xmd; -pub fn hash_to_field( +pub(crate) fn hash_to_field( ctx: &mut Context, fp_chip: &FpChip<'_, F>, sha256_chip: &Sha256Chip, @@ -33,10 +33,10 @@ fn bytes_to_registers( ) -> ProperCrtUint { assert_eq!(bytes.len(), 48); - let range = fp_chip.range; + let range = fp_chip.range(); let gate = range.gate(); - let mut assigned_int = Vec::>::new(); + let mut assigned_int = Vec::>::with_capacity(6); for (_, chunk) in bytes.chunks(8).enumerate() { let mut assigned_u64 = ctx.load_zero(); for (j, byte) in chunk.iter().enumerate() { diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs index bf0e27ff..116781a1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -142,7 +142,7 @@ fn y_den( a_plus_b_plus_c } -pub fn iso_map( +pub(crate) fn iso_map( ctx: &mut Context, fp_chip: &FpChip<'_, F>, x: ProperCrtUint, diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index a40d33f9..96c9b986 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -47,7 +47,7 @@ fn xy2_selector( (x, y2) } -pub fn map_to_curve( +pub(crate) fn map_to_curve( ctx: &mut Context, fp_chip: &FpChip<'_, F>, u: ProperCrtUint, @@ -74,7 +74,8 @@ pub fn map_to_curve( let tv2 = fp_chip.mul(ctx, tv1.clone(), tv1.clone()); // Step 3: x1 = tv1 + tv2 - let x1 = ProperCrtUint(fp_chip.add_no_carry(ctx, tv1.clone(), tv2.clone())); + let x1 = fp_chip.add_no_carry(ctx, tv1.clone(), tv2.clone()); + let x1 = fp_chip.carry_mod(ctx, x1); // Step 4: x1 = inv0(x1) let x1 = mod_inverse(ctx, fp_chip, x1); @@ -83,7 +84,8 @@ pub fn map_to_curve( let e1 = fp_chip.is_equal(ctx, x1.clone(), zero_int); // Step 6: x1 = x1 + 1 - let x1 = ProperCrtUint(fp_chip.add_no_carry(ctx, x1.clone(), one_int)); + let x1 = fp_chip.add_no_carry(ctx, x1.clone(), one_int); + let x1 = fp_chip.carry_mod(ctx, x1); // Step 7: x1 = e1 ? c2 : x1 let c2 = get_C2(ctx, range); @@ -98,14 +100,16 @@ pub fn map_to_curve( // Step 10: gx1 = gx1 + A let a = get_A(ctx, range); - let gx1 = ProperCrtUint(fp_chip.add_no_carry(ctx, gx1, a)); + let gx1 = fp_chip.add_no_carry(ctx, gx1, a); + let gx1 = fp_chip.carry_mod(ctx, gx1); // Step 11: gx1 = gx1 * x1 let gx1 = fp_chip.mul(ctx, gx1, x1.clone()); // Step 12: gx1 = gx1 + B # gx1 = g(x1) = x1^3 + A * x1 + B let b = get_B(ctx, range); - let gx1 = ProperCrtUint(fp_chip.add_no_carry(ctx, gx1, b)); + let gx1 = fp_chip.add_no_carry(ctx, gx1, b); + let gx1 = fp_chip.carry_mod(ctx, gx1); // Step 13: x2 = tv1 * x1 # x2 = Z * u^2 * x1 let x2 = fp_chip.mul(ctx, tv1.clone(), x1.clone()); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index 75fd7269..a4ecae71 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -2,7 +2,7 @@ use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; use crate::{bigint::ProperCrtUint, ecc::EcPoint}; -use self::hash_to_field::hash_to_field; +use self::{hash_to_field::hash_to_field, map_to_curve::map_to_curve}; use super::{sha256::Sha256Chip, Secp256k1Chip}; @@ -35,7 +35,7 @@ pub fn hash_to_curve( let (u0, u1) = hash_to_field(ctx, fp_chip, sha256_chip, msg_bytes); // Step 2: Q0 = map_to_curve(u[0]) - let (q0_x, q0_y2) = map_to_curve::map_to_curve( + let (q0_x, q0_y2) = map_to_curve( ctx, fp_chip, u0, @@ -47,7 +47,7 @@ pub fn hash_to_curve( ); // Step 3: Q1 = map_to_curve(u[1]) - let (q1_x, q1_y2) = map_to_curve::map_to_curve( + let (q1_x, q1_y2) = map_to_curve( ctx, fp_chip, u1, diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index 184756b2..ef4159c9 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -16,7 +16,7 @@ use crate::{ }, }; -pub fn byte_to_bits_le_assigned( +pub(crate) fn byte_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, byte: &AssignedValue, @@ -31,7 +31,7 @@ pub fn byte_to_bits_le_assigned( assigned_bits } -pub fn bytes_to_bits_le_assigned( +pub(crate) fn bytes_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, bytes: &[AssignedValue], @@ -39,7 +39,7 @@ pub fn bytes_to_bits_le_assigned( bytes.iter().flat_map(|byte| byte_to_bits_le_assigned(ctx, range, byte)).collect_vec() } -pub fn bits_le_to_byte_assigned( +pub(crate) fn bits_le_to_byte_assigned( ctx: &mut Context, range: &RangeChip, bits: &[AssignedValue], @@ -53,7 +53,7 @@ pub fn bits_le_to_byte_assigned( sum } -pub fn bits_le_to_bytes_assigned( +pub(crate) fn bits_le_to_bytes_assigned( ctx: &mut Context, range: &RangeChip, bits: &[AssignedValue], @@ -61,7 +61,7 @@ pub fn bits_le_to_bytes_assigned( bits.chunks(8).map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)).collect_vec() } -pub fn limbs_le_to_bigint( +pub(crate) fn limbs_le_to_bigint( ctx: &mut Context, range: &RangeChip, limbs: &[AssignedValue], @@ -90,7 +90,7 @@ pub fn limbs_le_to_bigint( int } -pub fn mod_inverse( +pub(crate) fn mod_inverse( ctx: &mut Context, fp_chip: &FpChip<'_, F>, num: ProperCrtUint, From 65713b911be52f7dd28952788017814bf352c661 Mon Sep 17 00:00:00 2001 From: shryasss Date: Tue, 13 Feb 2024 06:02:29 +0530 Subject: [PATCH 06/24] fix(wip): bigint conversion --- .../src/secp256k1/hash_to_curve/constants.rs | 365 +++++++++++++----- .../hash_to_curve/expand_message_xmd.rs | 31 +- .../secp256k1/hash_to_curve/hash_to_field.rs | 57 +-- .../src/secp256k1/hash_to_curve/iso_map.rs | 55 +-- .../secp256k1/hash_to_curve/map_to_curve.rs | 54 ++- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 114 +++++- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 70 ++-- halo2-ecc/src/secp256k1/sha256/mod.rs | 102 +++-- 8 files changed, 598 insertions(+), 250 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index f381b003..36dcbf19 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -1,7 +1,8 @@ -use halo2_base::{gates::RangeChip, utils::BigPrimeField, AssignedValue, Context}; - -use crate::bigint::ProperCrtUint; - +use halo2_base::{ gates::RangeChip, utils::BigPrimeField, AssignedValue, Context }; +use num_bigint::BigUint; +use num_integer::div_ceil; +use num_traits::Num; +use crate::{ bigint::ProperCrtUint, secp256k1::FpChip }; use super::util::limbs_le_to_bigint; pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { @@ -17,203 +18,389 @@ pub(crate) fn get_lib_str(ctx: &mut Context) -> Vec(ctx: &mut Context) -> Vec> { let dst_prime = [ - 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, - 99, 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, - 87, 85, 95, 82, 79, 95, 49, + 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, 99, + 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, 87, + 85, 95, 82, 79, 95, 49, ]; - dst_prime.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>() + dst_prime + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>() } +// Z = 115792089237316195423570985008687907853269984665640564039457584007908834671652 pub(crate) fn get_Z( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let z = - [18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615]; - let z = z.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, z.as_slice(), 64) + let z = BigUint::from_str_radix( + "115792089237316195423570985008687907853269984665640564039457584007908834671652", + 10 + ) + .unwrap() + .to_bytes_le(); + + let mut z_limbs = Vec::>::with_capacity(div_ceil(z.len(), 11)); + for chunk in z.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + z_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, z_limbs.as_slice()) } +// A = 28734576633528757162648956269730739219262246272443394170905244663053633733939 pub(crate) fn get_A( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let a = [4635408806871057715, 16813014259472469597, 11568152433342665330, 4577682160469023452]; - let a = a.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, a.as_slice(), 64) + let a = BigUint::from_str_radix( + "28734576633528757162648956269730739219262246272443394170905244663053633733939", + 10 + ) + .unwrap() + .to_bytes_le(); + + let mut a_limbs = Vec::>::with_capacity(div_ceil(a.len(), 11)); + for chunk in a.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + a_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, a_limbs.as_slice()) } pub(crate) fn get_B( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let b = [1771, 0, 0, 0]; - let b = b.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + let b = BigUint::from(1771).to_bytes_le(); + + let mut b_limbs = Vec::>::with_capacity(div_ceil(b.len(), 11)); + for chunk in b.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + b_limbs.push(limb); + } - limbs_le_to_bigint(ctx, range, b.as_slice(), 64) + limbs_le_to_bigint(ctx, range, fp_chip, b_limbs.as_slice()) } pub(crate) fn get_C1( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { let c1 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994]; - let c1 = c1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + let c1 = c1 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); - limbs_le_to_bigint(ctx, range, c1.as_slice(), 64) + limbs_le_to_bigint(ctx, range, fp_chip, c1.as_slice(), 64) } pub(crate) fn get_C2( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804]; - let c2 = c2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); + let c2 = c2 + .into_iter() + .map(F::from) + .map(|v| ctx.load_constant(v)) + .collect::>(); - limbs_le_to_bigint(ctx, range, c2.as_slice(), 64) + limbs_le_to_bigint(ctx, range, fp_chip, c2.as_slice(), 64) } +// k_(1,0) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7 pub(crate) fn get_k_1_0( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_1_0 = - [10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008]; - let k_1_0 = k_1_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_1_0.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(1,1) = 0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581 pub(crate) fn get_k_1_1( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_1_1 = - [16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237]; - let k_1_1 = k_1_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_1_1.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(1,2) = 0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262 pub(crate) fn get_k_1_2( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_1_2 = - [5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894]; - let k_1_2 = k_1_2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_1_2.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(1,3) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c pub(crate) fn get_k_1_3( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_1_3 = - [10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008]; - let k_1_3 = k_1_3.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_1_3.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(2,0) = 0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b pub(crate) fn get_k_2_0( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_2_0 = - [11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418]; - let k_2_0 = k_2_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_2_0.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(2,1) = 0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14 pub(crate) fn get_k_2_1( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_2_1 = - [14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821]; - let k_2_1 = k_2_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_2_1.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(3,0) = 0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c pub(crate) fn get_k_3_0( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_3_0 = - [11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071]; - let k_3_0 = k_3_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_3_0.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(3,1) = 0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3 pub(crate) fn get_k_3_1( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_3_1 = - [16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615]; - let k_3_1 = k_3_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_3_1.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(3,2) = 0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931 pub(crate) fn get_k_3_2( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_3_2 = - [12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947]; - let k_3_2 = k_3_2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_3_2.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(3,3) = 0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84 pub(crate) fn get_k_3_3( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_3_3 = - [9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669]; - let k_3_3 = k_3_3.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_3_3.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(4,0) = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b pub(crate) fn get_k_4_0( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_4_0 = - [18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615]; - let k_4_0 = k_4_0.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_4_0.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(4,1) = 0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573 pub(crate) fn get_k_4_1( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_4_1 = - [16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023]; - let k_4_1 = k_4_1.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_4_1.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } +// k_(4,2) = 0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f pub(crate) fn get_k_4_2( ctx: &mut Context, range: &RangeChip, + fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_4_2 = - [12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116]; - let k_4_2 = k_4_2.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>(); - - limbs_le_to_bigint(ctx, range, k_4_2.as_slice(), 64) + let k_bytes = BigUint::from_str_radix( + "0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f", + 16 + ) + .unwrap() + .to_bytes_le(); + + let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); + for chunk in k_bytes.chunks(11) { + let limb = ctx.load_witness(F::from_bytes_le(chunk)); + k_limbs.push(limb); + } + + limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index cf1530e1..58c6d428 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -1,14 +1,16 @@ use halo2_base::{ - gates::{GateInstructions, RangeChip, RangeInstructions}, + gates::{ GateInstructions, RangeChip, RangeInstructions }, utils::BigPrimeField, - AssignedValue, Context, QuantumCell, + AssignedValue, + Context, + QuantumCell, }; use crate::secp256k1::sha256::Sha256Chip; use super::{ - constants::{get_dst_prime, get_lib_str, get_z_pad}, - util::{bits_le_to_bytes_assigned, bytes_to_bits_le_assigned}, + constants::{ get_dst_prime, get_lib_str, get_z_pad }, + util::{ bits_le_to_bytes_assigned, bytes_to_bits_le_assigned }, }; fn calc_msg_prime_output_length(msg_length: usize) -> usize { @@ -17,7 +19,7 @@ fn calc_msg_prime_output_length(msg_length: usize) -> usize { fn msg_prime( ctx: &mut Context, - msg_bytes: &[AssignedValue], + msg_bytes: &[AssignedValue] ) -> Vec> { let zero = ctx.load_zero(); @@ -25,8 +27,9 @@ fn msg_prime( let lib_str = get_lib_str(ctx); let dst_prime = get_dst_prime(ctx); - let mut msg_prime = - Vec::>::with_capacity(calc_msg_prime_output_length(msg_bytes.len())); + let mut msg_prime = Vec::>::with_capacity( + calc_msg_prime_output_length(msg_bytes.len()) + ); // msg_prme = z_pad ... msg_prime.extend(z_pad); @@ -49,10 +52,10 @@ fn msg_prime( fn hash_msg_prime_to_b0( ctx: &mut Context, sha256_chip: &Sha256Chip<'_, F>, - msg_prime_bytes: &[AssignedValue], + msg_prime_bytes: &[AssignedValue] ) -> Vec> { let msg_prime_bytes = msg_prime_bytes.iter().map(|byte| QuantumCell::Existing(*byte)); - let hash = sha256_chip.digest(ctx, msg_prime_bytes).unwrap(); + let hash = sha256_chip.digest_le(ctx, msg_prime_bytes).unwrap(); hash } @@ -62,7 +65,7 @@ fn hash_bi( sha256_chip: &Sha256Chip, b_idx_byte: &AssignedValue, b0_bytes: &[AssignedValue], - bi_minus_one_bytes: &[AssignedValue], + bi_minus_one_bytes: &[AssignedValue] ) -> Vec> { let b0_bits = bytes_to_bits_le_assigned(ctx, range, b0_bytes); let bi_minus_one_bits = bytes_to_bits_le_assigned(ctx, range, bi_minus_one_bytes); @@ -79,7 +82,7 @@ fn hash_b( ctx: &mut Context, sha256_chip: &Sha256Chip<'_, F>, b_idx_byte: &AssignedValue, - b_bytes: &Vec>, + b_bytes: &Vec> ) -> Vec> { let dst_prime = get_dst_prime(ctx); @@ -89,7 +92,7 @@ fn hash_b( preimage.extend(dst_prime); let preimage = preimage.iter().map(|byte| QuantumCell::Existing(*byte)); - let hash = sha256_chip.digest(ctx, preimage).unwrap(); + let hash = sha256_chip.digest_le(ctx, preimage).unwrap(); hash } @@ -98,7 +101,7 @@ fn str_xor( ctx: &mut Context, range: &RangeChip, a_bits: &[AssignedValue], - b_bits: &[AssignedValue], + b_bits: &[AssignedValue] ) -> Vec> { assert_eq!(a_bits.len(), b_bits.len()); @@ -117,7 +120,7 @@ pub(crate) fn expand_message_xmd( ctx: &mut Context, range: &RangeChip, sha256_chip: &Sha256Chip, - msg_bytes: &[AssignedValue], + msg_bytes: &[AssignedValue] ) -> Vec> { let one = ctx.load_constant(F::from(1)); let two = ctx.load_constant(F::from(2)); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index a3bf87c4..07d45703 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -1,13 +1,18 @@ use halo2_base::{ - gates::{GateInstructions, RangeInstructions}, + gates::{ GateInstructions, RangeInstructions }, utils::BigPrimeField, - AssignedValue, Context, QuantumCell, + AssignedValue, + Context, + QuantumCell, }; +use itertools::Itertools; +use num_bigint::BigUint; +use num_integer::div_ceil; use crate::{ bigint::ProperCrtUint, fields::FieldChip, - secp256k1::{hash_to_curve::util::limbs_le_to_bigint, sha256::Sha256Chip, FpChip}, + secp256k1::{ hash_to_curve::util::limbs_le_to_bigint, sha256::Sha256Chip, FpChip }, }; use super::expand_message_xmd::expand_message_xmd; @@ -16,7 +21,7 @@ pub(crate) fn hash_to_field( ctx: &mut Context, fp_chip: &FpChip<'_, F>, sha256_chip: &Sha256Chip, - msg_bytes: &[AssignedValue], + msg_bytes: &[AssignedValue] ) -> (ProperCrtUint, ProperCrtUint) { let expanded_msg_bytes = expand_message_xmd(ctx, fp_chip.range, sha256_chip, msg_bytes); @@ -29,28 +34,34 @@ pub(crate) fn hash_to_field( fn bytes_to_registers( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - bytes: &[AssignedValue], + bytes: &[AssignedValue] ) -> ProperCrtUint { - assert_eq!(bytes.len(), 48); - - let range = fp_chip.range(); - let gate = range.gate(); - - let mut assigned_int = Vec::>::with_capacity(6); - for (_, chunk) in bytes.chunks(8).enumerate() { - let mut assigned_u64 = ctx.load_zero(); - for (j, byte) in chunk.iter().enumerate() { - assigned_u64 = gate.mul_add( - ctx, - QuantumCell::Existing(*byte), - QuantumCell::Constant(F::from(1 << (8 * j))), - QuantumCell::Existing(assigned_u64), - ); + let mut limbs = Vec::>::with_capacity(bytes.len() / 8); + for chunk in bytes.chunks(11) { + let mut limb = ctx.load_zero(); + for i in 0..11 { + if chunk.len() < 11 && i >= chunk.len() { + break; + } + limb = fp_chip + .range() + .gate() + .mul_add(ctx, chunk[i], QuantumCell::Constant(F::from(1 << (8 * i))), limb); } - assigned_int.push(assigned_u64); + limbs.push(limb); } - let int = limbs_le_to_bigint(ctx, range, &assigned_int, 64); + let assigned_ints = limbs + .iter() + .map(|limb| { limbs_le_to_bigint(ctx, fp_chip.range(), fp_chip, &[*limb], 88) }) + .collect_vec(); - fp_chip.carry_mod(ctx, int.into()) + // let mut assigned_int = assigned_ints[0]; + // for (i, int) in assigned_ints.iter().enumerate() { + // let multiplier = fp_chip.load_constant_uint(ctx, BigUint::from(2u8).pow((88 * i) as u32)); + // let limb = fp_chip.mul_no_carry(ctx, *int, multiplier); + // assigned_int = fp_chip.add_no_carry(ctx, assigned_int, limb); + // } + + fp_chip.load_constant_uint(ctx, BigUint::from(1u64)) // TODO } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs index 116781a1..25f60d3d 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -1,10 +1,21 @@ -use halo2_base::{utils::BigPrimeField, Context}; +use halo2_base::{ utils::BigPrimeField, Context }; -use crate::{bigint::ProperCrtUint, fields::FieldChip, secp256k1::FpChip}; +use crate::{ bigint::ProperCrtUint, fields::FieldChip, secp256k1::FpChip }; use super::constants::{ - get_k_1_0, get_k_1_1, get_k_1_2, get_k_1_3, get_k_2_0, get_k_2_1, get_k_3_0, get_k_3_1, - get_k_3_2, get_k_3_3, get_k_4_0, get_k_4_1, get_k_4_2, + get_k_1_0, + get_k_1_1, + get_k_1_2, + get_k_1_3, + get_k_2_0, + get_k_2_1, + get_k_3_0, + get_k_3_1, + get_k_3_2, + get_k_3_3, + get_k_4_0, + get_k_4_1, + get_k_4_2, }; fn x_num( @@ -12,14 +23,14 @@ fn x_num( fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint, + x_3: ProperCrtUint ) -> ProperCrtUint { let range = fp_chip.range(); - let k_1_3 = get_k_1_3(ctx, range); - let k_1_2 = get_k_1_2(ctx, range); - let k_1_1 = get_k_1_1(ctx, range); - let k_1_0 = get_k_1_0(ctx, range); + let k_1_3 = get_k_1_3(ctx, range, fp_chip); + let k_1_2 = get_k_1_2(ctx, range, fp_chip); + let k_1_1 = get_k_1_1(ctx, range, fp_chip); + let k_1_0 = get_k_1_0(ctx, range, fp_chip); // Step 1: a = k_(1,3) * x'^3 let a = fp_chip.mul(ctx, k_1_3, x_3); @@ -49,12 +60,12 @@ fn x_den( ctx: &mut Context, fp_chip: &FpChip<'_, F>, x: ProperCrtUint, - x_2: ProperCrtUint, + x_2: ProperCrtUint ) -> ProperCrtUint { let range = fp_chip.range(); - let k_2_0 = get_k_2_0(ctx, range); - let k_2_1 = get_k_2_1(ctx, range); + let k_2_0 = get_k_2_0(ctx, range, fp_chip); + let k_2_1 = get_k_2_1(ctx, range, fp_chip); // Step 1: a = x_2 + k_2_0 let a = fp_chip.add_no_carry(ctx, x_2, k_2_0); @@ -75,14 +86,14 @@ fn y_num( fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint, + x_3: ProperCrtUint ) -> ProperCrtUint { let range = fp_chip.range(); - let k_3_3 = get_k_3_3(ctx, range); - let k_3_2 = get_k_3_2(ctx, range); - let k_3_1 = get_k_3_1(ctx, range); - let k_3_0 = get_k_3_0(ctx, range); + let k_3_3 = get_k_3_3(ctx, range, fp_chip); + let k_3_2 = get_k_3_2(ctx, range, fp_chip); + let k_3_1 = get_k_3_1(ctx, range, fp_chip); + let k_3_0 = get_k_3_0(ctx, range, fp_chip); // Step 1: a = k_3_3 * x_3 let a = fp_chip.mul(ctx, k_3_3, x_3); @@ -113,13 +124,13 @@ fn y_den( fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint, + x_3: ProperCrtUint ) -> ProperCrtUint { let range = fp_chip.range(); - let k_4_0 = get_k_4_0(ctx, range); - let k_4_1 = get_k_4_1(ctx, range); - let k_4_2 = get_k_4_2(ctx, range); + let k_4_0 = get_k_4_0(ctx, range, fp_chip); + let k_4_1 = get_k_4_1(ctx, range, fp_chip); + let k_4_2 = get_k_4_2(ctx, range, fp_chip); // Step 1: a = x_3 + k_4_0 let a = fp_chip.add_no_carry(ctx, x_3, k_4_0); @@ -148,7 +159,7 @@ pub(crate) fn iso_map( x: ProperCrtUint, y: ProperCrtUint, x_mapped: ProperCrtUint, - y_mapped: ProperCrtUint, + y_mapped: ProperCrtUint ) { let one = ctx.load_constant(F::ONE); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 96c9b986..68aaf177 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -1,18 +1,11 @@ -use halo2_base::{ - gates::{GateInstructions, RangeInstructions}, - utils::BigPrimeField, - Context, -}; +use halo2_base::{ gates::{ GateInstructions, RangeInstructions }, utils::BigPrimeField, Context }; use num_bigint::BigUint; use crate::{ bigint::ProperCrtUint, - fields::{FieldChip, Selectable}, + fields::{ FieldChip, Selectable }, secp256k1::{ - hash_to_curve::{ - constants::{get_A, get_B, get_C1, get_C2, get_Z}, - iso_map::iso_map, - }, + hash_to_curve::{ constants::{ get_A, get_B, get_C1, get_C2, get_Z }, iso_map::iso_map }, FpChip, }, }; @@ -27,7 +20,7 @@ fn xy2_selector( gx2: ProperCrtUint, gx2_sqrt: ProperCrtUint, x1: ProperCrtUint, - x2: ProperCrtUint, + x2: ProperCrtUint ) -> (ProperCrtUint, ProperCrtUint) { let gate = fp_chip.range.gate(); let one = ctx.load_constant(F::ONE); @@ -55,20 +48,43 @@ pub(crate) fn map_to_curve( gx2_sqrt: ProperCrtUint, y_pos: ProperCrtUint, x_mapped: ProperCrtUint, - y_mapped: ProperCrtUint, + y_mapped: ProperCrtUint ) -> (ProperCrtUint, ProperCrtUint) { let range = fp_chip.range(); let gate = range.gate(); + let zero = ctx.load_zero(); let one = ctx.load_constant(F::ONE); let zero_int = fp_chip.load_constant_uint(ctx, BigUint::from(0u64)); let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); // Step 1: tv1 = Z * u^2 - let u_sq = fp_chip.mul(ctx, u.clone(), u.clone()); - let z = get_Z(ctx, range); - let tv1 = fp_chip.mul(ctx, z, u_sq); + let u_sq = fp_chip.mul_no_carry(ctx, u.clone(), u.clone()); + let u_sq = fp_chip.carry_mod(ctx, u_sq); + let z = get_Z(ctx, range, fp_chip); + println!("reach here 1"); + // if z.0.truncation.limbs.len() != u_sq.0.truncation.limbs.len() { + // println!("entered here"); + // if z.0.truncation.limbs.len() > u_sq.0.truncation.limbs.len() { + // let diff = z.0.truncation.limbs.len() - u_sq.0.truncation.limbs.len(); + // println!("entered here 1: diff = {}", diff); + // for _ in 0..diff { + // u_sq.0.truncation.limbs.push(zero); + // } + // println!("len after push: {}", u_sq.0.truncation.limbs.len()); + // } else { + // let diff = u_sq.0.truncation.limbs.len() - z.0.truncation.limbs.len(); + // println!("entered here 2: diff = {}", diff); + // for _ in 0..diff { + // z.0.truncation.limbs.push(zero); + // } + // println!("len after push: {}", z.0.truncation.limbs.len()); + // } + // } + let tv1 = fp_chip.mul_no_carry(ctx, z, u_sq); + let tv1 = fp_chip.carry_mod(ctx, tv1); + println!("reach here 2"); // Step 2: tv2 = tv1^2 let tv2 = fp_chip.mul(ctx, tv1.clone(), tv1.clone()); @@ -88,18 +104,18 @@ pub(crate) fn map_to_curve( let x1 = fp_chip.carry_mod(ctx, x1); // Step 7: x1 = e1 ? c2 : x1 - let c2 = get_C2(ctx, range); + let c2 = get_C2(ctx, range, fp_chip); let x1 = fp_chip.select(ctx, c2, x1, e1); // Step 8: x1 = x1 * c1 # x1 = (-B / A) * (1 + (1 / (Z^2 * u^4 + Z * u^2))) - let c1 = get_C1(ctx, range); + let c1 = get_C1(ctx, range, fp_chip); let x1 = fp_chip.mul(ctx, x1.clone(), c1); // Step 9: gx1 = x1^2 let gx1 = fp_chip.mul(ctx, x1.clone(), x1.clone()); // Step 10: gx1 = gx1 + A - let a = get_A(ctx, range); + let a = get_A(ctx, range, fp_chip); let gx1 = fp_chip.add_no_carry(ctx, gx1, a); let gx1 = fp_chip.carry_mod(ctx, gx1); @@ -107,7 +123,7 @@ pub(crate) fn map_to_curve( let gx1 = fp_chip.mul(ctx, gx1, x1.clone()); // Step 12: gx1 = gx1 + B # gx1 = g(x1) = x1^3 + A * x1 + B - let b = get_B(ctx, range); + let b = get_B(ctx, range, fp_chip); let gx1 = fp_chip.add_no_carry(ctx, gx1, b); let gx1 = fp_chip.carry_mod(ctx, gx1); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index a4ecae71..d28b515c 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -1,10 +1,10 @@ -use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; +use halo2_base::{ utils::BigPrimeField, AssignedValue, Context }; -use crate::{bigint::ProperCrtUint, ecc::EcPoint}; +use crate::{ bigint::ProperCrtUint, ecc::EcPoint }; -use self::{hash_to_field::hash_to_field, map_to_curve::map_to_curve}; +use self::{ hash_to_field::hash_to_field, map_to_curve::map_to_curve }; -use super::{sha256::Sha256Chip, Secp256k1Chip}; +use super::{ sha256::Sha256Chip, Secp256k1Chip }; pub mod constants; pub mod expand_message_xmd; @@ -27,7 +27,7 @@ pub fn hash_to_curve( q1_gx2_sqrt: ProperCrtUint, q1_y_pos: ProperCrtUint, q1_x_mapped: ProperCrtUint, - q1_y_mapped: ProperCrtUint, + q1_y_mapped: ProperCrtUint ) -> EcPoint> { let fp_chip = secp256k1_chip.field_chip(); @@ -43,7 +43,7 @@ pub fn hash_to_curve( q0_gx2_sqrt, q0_y_pos, q0_x_mapped.clone(), - q0_y_mapped.clone(), + q0_y_mapped.clone() ); // Step 3: Q1 = map_to_curve(u[1]) @@ -55,7 +55,7 @@ pub fn hash_to_curve( q1_gx2_sqrt, q1_y_pos, q1_x_mapped.clone(), - q1_y_mapped.clone(), + q1_y_mapped.clone() ); // Step 4: return A + B @@ -66,3 +66,103 @@ pub fn hash_to_curve( point_add } + +#[cfg(test)] +mod test { + use halo2_base::{ + halo2_proofs::halo2curves::{ grumpkin::Fq as Fr, secp256k1::Secp256k1Affine, CurveAffine }, + utils::testing::base_test, + }; + + use crate::{ + ecc::EccChip, + fields::FieldChip, + secp256k1::{ sha256::Sha256Chip, FpChip, FqChip }, + }; + + use super::hash_to_curve; + + #[test] + fn test_hash_to_curve() { + // msg = "abc" + let msg = vec![97u64, 98u64, 99u64]; + let q0_gx1_sqrt = ::ScalarExt::from([ + 1664545361815120357u64, 10283872013620121914u64, 9380010581010034654u64, 4261145792225450732u64, + ]); + let q0_gx2_sqrt = ::ScalarExt::from([ + 1u64, 0u64, 0u64, 0u64, + ]); + let q0_y_pos = ::ScalarExt::from([ + 1664545361815120357u64, 10283872013620121914u64, 9380010581010034654u64, 4261145792225450732u64, + ]); + let q0_x_mapped = ::ScalarExt::from([ + 5925487804738118359u64, 4856574525535083224u64, 12797074899347248930u64, 566772074147120223u64, + ]); + let q0_y_mapped = ::ScalarExt::from([ + 4617496280555238207u64, 14690993926117989357u64, 3636581750055392523u64, 6937101362475356158u64, + ]); + let q1_gx1_sqrt = ::ScalarExt::from([ + 7355280221998350180u64, 4783425048112263089u64, 5071308975172430165u64, 3916832897263395160u64, + ]); + let q1_gx2_sqrt = ::ScalarExt::from([ + 1u64, 0u64, 0u64, 0u64, + ]); + let q1_y_pos = ::ScalarExt::from([ + 7355280221998350180u64, 4783425048112263089u64, 5071308975172430165u64, 3916832897263395160u64, + ]); + let q1_x_mapped = ::ScalarExt::from([ + 13296707460026998648u64, 318503968633800990u64, 15989839026330281858u64, 16856858595694562935u64, + ]); + let q1_y_mapped = ::ScalarExt::from([ + 1338026386978707379u64, 6209856281762218480u64, 13772974005733639516u64, 14629888772142879508u64, + ]); + + base_test() + .k(20) + .lookup_bits(19) + .expect_satisfied(true) + .run(|ctx, range| { + let fp_chip = FpChip::::new(range, 88, 3); + let fq_chip = FqChip::::new(range, 88, 3); + let ecc_chip = EccChip::>::new(&fp_chip); + + let sha256_chip = Sha256Chip::new(range); + + let msg_bytes = msg + .iter() + .map(|&x| ctx.load_witness(Fr::from(x))) + .collect::>(); + + let q0_gx1_sqrt = fq_chip.load_private(ctx, q0_gx1_sqrt); + let q0_gx2_sqrt = fq_chip.load_private(ctx, q0_gx2_sqrt); + let q0_y_pos = fq_chip.load_private(ctx, q0_y_pos); + let q0_x_mapped = fq_chip.load_private(ctx, q0_x_mapped); + let q0_y_mapped = fq_chip.load_private(ctx, q0_y_mapped); + let q1_gx1_sqrt = fq_chip.load_private(ctx, q1_gx1_sqrt); + let q1_gx2_sqrt = fq_chip.load_private(ctx, q1_gx2_sqrt); + let q1_y_pos = fq_chip.load_private(ctx, q1_y_pos); + let q1_x_mapped = fq_chip.load_private(ctx, q1_x_mapped); + let q1_y_mapped = fq_chip.load_private(ctx, q1_y_mapped); + + let point = hash_to_curve( + ctx, + ecc_chip, + &sha256_chip, + msg_bytes.as_slice(), + q0_gx1_sqrt, + q0_gx2_sqrt, + q0_y_pos, + q0_x_mapped, + q0_y_mapped, + q1_gx1_sqrt, + q1_gx2_sqrt, + q1_y_pos, + q1_x_mapped, + q1_y_mapped + ); + + println!("point x: {:?}", point.x); + println!("point y: {:?}", point.y); + }) + } +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index ef4159c9..4da4e2ac 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -1,29 +1,30 @@ use halo2_base::{ - gates::{GateInstructions, RangeChip, RangeInstructions}, - utils::BigPrimeField, - AssignedValue, Context, QuantumCell, + gates::{ GateInstructions, RangeChip, RangeInstructions }, + utils::{ fe_to_biguint, BigPrimeField }, + AssignedValue, + Context, + QuantumCell, }; use itertools::Itertools; -use num_bigint::BigUint; +use num_bigint::{ BigUint, ToBigInt }; use num_traits::Pow; use crate::{ - bigint::{ProperCrtUint, ProperUint}, + bigint::{ CRTInteger, OverflowInteger, ProperCrtUint }, fields::FieldChip, - secp256k1::{ - util::{bits_le_to_fe_assigned, fe_to_bits_le}, - FpChip, - }, + secp256k1::{ util::{ bits_le_to_fe_assigned, fe_to_bits_le }, FpChip }, }; pub(crate) fn byte_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, - byte: &AssignedValue, + byte: &AssignedValue ) -> Vec> { let bits = fe_to_bits_le(byte.value(), 8); - let assigned_bits = - bits.iter().map(|bit| ctx.load_constant(F::from(*bit as u64))).collect_vec(); + let assigned_bits = bits + .iter() + .map(|bit| ctx.load_constant(F::from(*bit as u64))) + .collect_vec(); let _byte = bits_le_to_fe_assigned(ctx, range, &assigned_bits).unwrap(); ctx.constrain_equal(byte, &_byte); @@ -34,15 +35,18 @@ pub(crate) fn byte_to_bits_le_assigned( pub(crate) fn bytes_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, - bytes: &[AssignedValue], + bytes: &[AssignedValue] ) -> Vec> { - bytes.iter().flat_map(|byte| byte_to_bits_le_assigned(ctx, range, byte)).collect_vec() + bytes + .iter() + .flat_map(|byte| byte_to_bits_le_assigned(ctx, range, byte)) + .collect_vec() } pub(crate) fn bits_le_to_byte_assigned( ctx: &mut Context, range: &RangeChip, - bits: &[AssignedValue], + bits: &[AssignedValue] ) -> AssignedValue { assert_eq!(bits.len(), 8); let gate = range.gate(); @@ -56,44 +60,40 @@ pub(crate) fn bits_le_to_byte_assigned( pub(crate) fn bits_le_to_bytes_assigned( ctx: &mut Context, range: &RangeChip, - bits: &[AssignedValue], + bits: &[AssignedValue] ) -> Vec> { - bits.chunks(8).map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)).collect_vec() + bits.chunks(8) + .map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)) + .collect_vec() } pub(crate) fn limbs_le_to_bigint( ctx: &mut Context, range: &RangeChip, - limbs: &[AssignedValue], - max_limb_bits: usize, + fp_chip: &FpChip<'_, F>, + limbs: &[AssignedValue] ) -> ProperCrtUint { - let native_limbs = limbs.iter().map(|limb| *limb.value()).collect_vec(); - let mut value = BigUint::from(0u64); - let mut limb_bases = Vec::::with_capacity(native_limbs.len()); - for (idx, limb) in native_limbs.iter().enumerate() { - let limb = BigUint::from_bytes_le(limb.to_bytes_le().as_slice()); - let limb_base = BigUint::from(2u64).pow(BigUint::from(idx) * BigUint::from(max_limb_bits)); - limb_bases.push(F::from_bytes_le(limb_base.to_bytes_le().as_slice())); - let shifted_limb = limb * limb_base; - value += shifted_limb; + for i in 0..limbs.len() { + value += (BigUint::from(1u64) << (88 * i)) * fe_to_biguint(limbs[i].value()); } - let int = ProperUint(limbs.to_vec()).into_crt( + let assigned_uint = OverflowInteger::new(limbs.to_vec(), 88); + let assigned_native = OverflowInteger::evaluate_native( ctx, - range.gate(), - value, - limb_bases.as_slice(), - max_limb_bits, + fp_chip.range().gate(), + limbs.to_vec(), + &fp_chip.limb_bases ); + let assigned_uint = CRTInteger::new(assigned_uint, assigned_native, value.to_bigint().unwrap()); - int + ProperCrtUint(assigned_uint) } pub(crate) fn mod_inverse( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - num: ProperCrtUint, + num: ProperCrtUint ) -> ProperCrtUint { let one = ctx.load_constant(F::ONE); let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); diff --git a/halo2-ecc/src/secp256k1/sha256/mod.rs b/halo2-ecc/src/secp256k1/sha256/mod.rs index a74119ae..749596bd 100644 --- a/halo2-ecc/src/secp256k1/sha256/mod.rs +++ b/halo2-ecc/src/secp256k1/sha256/mod.rs @@ -1,12 +1,14 @@ use halo2_base::{ - gates::{GateInstructions, RangeChip, RangeInstructions}, + gates::{ GateInstructions, RangeChip, RangeInstructions }, halo2_proofs::plonk::Error, utils::BigPrimeField, - AssignedValue, Context, QuantumCell, + AssignedValue, + Context, + QuantumCell, }; use itertools::Itertools; -use self::compression::{sha256_compression, INIT_STATE}; +use self::compression::{ sha256_compression, INIT_STATE }; use self::spread::SpreadChip; @@ -33,7 +35,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { &self, ctx: &mut Context, input: impl IntoIterator>, - max_len: usize, + max_len: usize ) -> Result>, Error> { let max_processed_bytes = { let mut max_bytes = max_len + 9; @@ -46,11 +48,13 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { let mut assigned_input_bytes = input .into_iter() - .map(|cell| match cell { - QuantumCell::Existing(v) => v, - QuantumCell::Witness(v) => ctx.load_witness(v), - QuantumCell::Constant(v) => ctx.load_constant(v), - _ => unreachable!(), + .map(|cell| { + match cell { + QuantumCell::Existing(v) => v, + QuantumCell::Witness(v) => ctx.load_witness(v), + QuantumCell::Constant(v) => ctx.load_constant(v), + _ => unreachable!(), + } }) .collect_vec(); @@ -93,10 +97,12 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { // compute an initial state from the precomputed_input. let last_state = INIT_STATE; - let mut assigned_last_state_vec = vec![last_state - .iter() - .map(|state| ctx.load_witness(F::from(*state as u64))) - .collect_vec()]; + let mut assigned_last_state_vec = vec![ + last_state + .iter() + .map(|state| ctx.load_witness(F::from(*state as u64))) + .collect_vec() + ]; let mut num_processed_input = 0; while num_processed_input < max_processed_bytes { @@ -106,7 +112,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { ctx, &self.spread, assigned_input_word_at_round, - assigned_last_state_vec.last().unwrap(), + assigned_last_state_vec.last().unwrap() )?; assigned_last_state_vec.push(new_assigned_hs_out); @@ -119,7 +125,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { let selector = gate.is_equal( ctx, QuantumCell::Constant(F::from(n_round as u64)), - assigned_num_round, + assigned_num_round ); for i in 0..8 { output_h_out[i] = gate.select(ctx, assigned_state[i], output_h_out[i], selector); @@ -142,7 +148,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { ctx, assigned_byte, QuantumCell::Constant(F::from(1u64 << (24 - 8 * idx))), - sum, + sum ); } ctx.constrain_equal(&assigned_word, &sum); @@ -156,22 +162,32 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { pub fn digest( &self, ctx: &mut Context, - input: impl IntoIterator>, + input: impl IntoIterator> ) -> Result>, Error> { let input = input.into_iter().collect_vec(); let input_len = input.len(); self.digest_varlen(ctx, input, input_len) } + + pub fn digest_le( + &self, + ctx: &mut Context, + input: impl IntoIterator> + ) -> Result>, Error> { + self.digest(ctx, input) + } } #[cfg(test)] mod test { use halo2_base::{ - gates::RangeInstructions, halo2_proofs::halo2curves::grumpkin::Fq as Fr, - utils::testing::base_test, QuantumCell, + gates::RangeInstructions, + halo2_proofs::halo2curves::grumpkin::Fq as Fr, + utils::testing::base_test, + QuantumCell, }; use itertools::Itertools; - use sha2::{Digest, Sha256}; + use sha2::{ Digest, Sha256 }; use super::Sha256Chip; @@ -183,27 +199,31 @@ mod test { hasher.update(preimage); let result = hasher.finalize(); - base_test().k(14).lookup_bits(13).expect_satisfied(true).run(|ctx, range| { - let preimage_assigned = preimage - .iter() - .map(|byte| QuantumCell::Existing(ctx.load_witness(Fr::from(*byte as u64)))) - .collect_vec(); + base_test() + .k(14) + .lookup_bits(13) + .expect_satisfied(true) + .run(|ctx, range| { + let preimage_assigned = preimage + .iter() + .map(|byte| QuantumCell::Existing(ctx.load_witness(Fr::from(*byte as u64)))) + .collect_vec(); - let result_assinged = result - .iter() - .map(|byte| { - let assigned = ctx.load_witness(Fr::from(*byte as u64)); - range.range_check(ctx, assigned, 8); - assigned - }) - .collect_vec(); - - let sha256_chip = Sha256Chip::new(range); - let digest = sha256_chip.digest(ctx, preimage_assigned).unwrap(); - - for (assigned, expected) in digest.iter().zip(result_assinged.iter()) { - ctx.constrain_equal(assigned, expected); - } - }) + let result_assinged = result + .iter() + .map(|byte| { + let assigned = ctx.load_witness(Fr::from(*byte as u64)); + range.range_check(ctx, assigned, 8); + assigned + }) + .collect_vec(); + + let sha256_chip = Sha256Chip::new(range); + let digest = sha256_chip.digest(ctx, preimage_assigned).unwrap(); + + for (assigned, expected) in digest.iter().zip(result_assinged.iter()) { + ctx.constrain_equal(assigned, expected); + } + }) } } From 657276d978d0c70e89fbc81a4ed4f6ada54b312e Mon Sep 17 00:00:00 2001 From: shryasss Date: Tue, 13 Feb 2024 08:19:20 +0530 Subject: [PATCH 07/24] fix(wip): hash_to_curve_working --- .../src/secp256k1/hash_to_curve/constants.rs | 337 ++++++------------ .../secp256k1/hash_to_curve/hash_to_field.rs | 33 +- .../secp256k1/hash_to_curve/map_to_curve.rs | 28 +- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 4 +- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 21 +- 5 files changed, 142 insertions(+), 281 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index 36dcbf19..514ad2e3 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -35,20 +35,14 @@ pub(crate) fn get_Z( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let z = BigUint::from_str_radix( - "115792089237316195423570985008687907853269984665640564039457584007908834671652", - 10 - ) - .unwrap() - .to_bytes_le(); - - let mut z_limbs = Vec::>::with_capacity(div_ceil(z.len(), 11)); - for chunk in z.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - z_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, z_limbs.as_slice()) + let z = [ + 18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615, + ] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, z.as_slice()) } // A = 28734576633528757162648956269730739219262246272443394170905244663053633733939 @@ -57,20 +51,12 @@ pub(crate) fn get_A( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let a = BigUint::from_str_radix( - "28734576633528757162648956269730739219262246272443394170905244663053633733939", - 10 - ) - .unwrap() - .to_bytes_le(); - - let mut a_limbs = Vec::>::with_capacity(div_ceil(a.len(), 11)); - for chunk in a.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - a_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, a_limbs.as_slice()) + let a = [4635408806871057715, 16813014259472469597, 11568152433342665330, 4577682160469023452] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, a.as_slice()) } pub(crate) fn get_B( @@ -78,15 +64,12 @@ pub(crate) fn get_B( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let b = BigUint::from(1771).to_bytes_le(); - - let mut b_limbs = Vec::>::with_capacity(div_ceil(b.len(), 11)); - for chunk in b.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - b_limbs.push(limb); - } + let b = [1771, 0, 0, 0] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, b_limbs.as_slice()) + limbs_le_to_bigint(ctx, range, fp_chip, b.as_slice()) } pub(crate) fn get_C1( @@ -94,14 +77,12 @@ pub(crate) fn get_C1( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let c1 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994]; - let c1 = c1 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) + let c1 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, c1.as_slice(), 64) + limbs_le_to_bigint(ctx, range, fp_chip, c1.as_slice()) } pub(crate) fn get_C2( @@ -109,14 +90,12 @@ pub(crate) fn get_C2( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804]; - let c2 = c2 - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) + let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, c2.as_slice(), 64) + limbs_le_to_bigint(ctx, range, fp_chip, c2.as_slice()) } // k_(1,0) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7 @@ -125,20 +104,12 @@ pub(crate) fn get_k_1_0( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(1,1) = 0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581 @@ -147,20 +118,12 @@ pub(crate) fn get_k_1_1( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(1,2) = 0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262 @@ -169,20 +132,12 @@ pub(crate) fn get_k_1_2( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(1,3) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c @@ -191,20 +146,12 @@ pub(crate) fn get_k_1_3( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(2,0) = 0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b @@ -213,20 +160,12 @@ pub(crate) fn get_k_2_0( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(2,1) = 0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14 @@ -235,20 +174,12 @@ pub(crate) fn get_k_2_1( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(3,0) = 0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c @@ -257,20 +188,12 @@ pub(crate) fn get_k_3_0( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(3,1) = 0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3 @@ -279,20 +202,12 @@ pub(crate) fn get_k_3_1( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(3,2) = 0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931 @@ -301,20 +216,12 @@ pub(crate) fn get_k_3_2( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(3,3) = 0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84 @@ -323,20 +230,12 @@ pub(crate) fn get_k_3_3( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(4,0) = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b @@ -345,20 +244,14 @@ pub(crate) fn get_k_4_0( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [ + 18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615, + ] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(4,1) = 0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573 @@ -367,20 +260,12 @@ pub(crate) fn get_k_4_1( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } // k_(4,2) = 0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f @@ -389,18 +274,10 @@ pub(crate) fn get_k_4_2( range: &RangeChip, fp_chip: &FpChip<'_, F> ) -> ProperCrtUint { - let k_bytes = BigUint::from_str_radix( - "0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f", - 16 - ) - .unwrap() - .to_bytes_le(); - - let mut k_limbs = Vec::>::with_capacity(div_ceil(k_bytes.len(), 11)); - for chunk in k_bytes.chunks(11) { - let limb = ctx.load_witness(F::from_bytes_le(chunk)); - k_limbs.push(limb); - } - - limbs_le_to_bigint(ctx, range, fp_chip, k_limbs.as_slice()) + let k = [12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116] + .iter() + .map(|v| ctx.load_witness(F::from(*v))) + .collect::>(); + + limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index 07d45703..c463ccc4 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -5,7 +5,6 @@ use halo2_base::{ Context, QuantumCell, }; -use itertools::Itertools; use num_bigint::BigUint; use num_integer::div_ceil; @@ -36,11 +35,11 @@ fn bytes_to_registers( fp_chip: &FpChip<'_, F>, bytes: &[AssignedValue] ) -> ProperCrtUint { - let mut limbs = Vec::>::with_capacity(bytes.len() / 8); - for chunk in bytes.chunks(11) { + let mut limbs = Vec::>::with_capacity(div_ceil(bytes.len(), 8)); + for chunk in bytes.chunks(8) { let mut limb = ctx.load_zero(); - for i in 0..11 { - if chunk.len() < 11 && i >= chunk.len() { + for i in 0..8 { + if chunk.len() < 8 && i >= chunk.len() { break; } limb = fp_chip @@ -51,17 +50,19 @@ fn bytes_to_registers( limbs.push(limb); } - let assigned_ints = limbs - .iter() - .map(|limb| { limbs_le_to_bigint(ctx, fp_chip.range(), fp_chip, &[*limb], 88) }) - .collect_vec(); + let mut lo_limbs = limbs[..3].to_vec(); + lo_limbs.push(ctx.load_zero()); + let mut hi_limbs = limbs[3..].to_vec(); + hi_limbs.push(ctx.load_zero()); - // let mut assigned_int = assigned_ints[0]; - // for (i, int) in assigned_ints.iter().enumerate() { - // let multiplier = fp_chip.load_constant_uint(ctx, BigUint::from(2u8).pow((88 * i) as u32)); - // let limb = fp_chip.mul_no_carry(ctx, *int, multiplier); - // assigned_int = fp_chip.add_no_carry(ctx, assigned_int, limb); - // } + let lo = limbs_le_to_bigint(ctx, fp_chip.range(), fp_chip, lo_limbs.as_slice()); + let hi = limbs_le_to_bigint(ctx, fp_chip.range(), fp_chip, hi_limbs.as_slice()); - fp_chip.load_constant_uint(ctx, BigUint::from(1u64)) // TODO + let two_power_192 = fp_chip.load_constant_uint(ctx, BigUint::from(1u64) << 192); + + let num = fp_chip.mul_no_carry(ctx, hi, two_power_192); + let num = fp_chip.add_no_carry(ctx, num, lo); + let num = fp_chip.carry_mod(ctx, num); + + num } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 68aaf177..563e04b0 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -60,31 +60,9 @@ pub(crate) fn map_to_curve( let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); // Step 1: tv1 = Z * u^2 - let u_sq = fp_chip.mul_no_carry(ctx, u.clone(), u.clone()); - let u_sq = fp_chip.carry_mod(ctx, u_sq); + let u_sq = fp_chip.mul(ctx, u.clone(), u.clone()); let z = get_Z(ctx, range, fp_chip); - println!("reach here 1"); - // if z.0.truncation.limbs.len() != u_sq.0.truncation.limbs.len() { - // println!("entered here"); - // if z.0.truncation.limbs.len() > u_sq.0.truncation.limbs.len() { - // let diff = z.0.truncation.limbs.len() - u_sq.0.truncation.limbs.len(); - // println!("entered here 1: diff = {}", diff); - // for _ in 0..diff { - // u_sq.0.truncation.limbs.push(zero); - // } - // println!("len after push: {}", u_sq.0.truncation.limbs.len()); - // } else { - // let diff = u_sq.0.truncation.limbs.len() - z.0.truncation.limbs.len(); - // println!("entered here 2: diff = {}", diff); - // for _ in 0..diff { - // z.0.truncation.limbs.push(zero); - // } - // println!("len after push: {}", z.0.truncation.limbs.len()); - // } - // } - let tv1 = fp_chip.mul_no_carry(ctx, z, u_sq); - let tv1 = fp_chip.carry_mod(ctx, tv1); - println!("reach here 2"); + let tv1 = fp_chip.mul(ctx, z, u_sq); // Step 2: tv2 = tv1^2 let tv2 = fp_chip.mul(ctx, tv1.clone(), tv1.clone()); @@ -94,7 +72,9 @@ pub(crate) fn map_to_curve( let x1 = fp_chip.carry_mod(ctx, x1); // Step 4: x1 = inv0(x1) + println!("reach here 1"); let x1 = mod_inverse(ctx, fp_chip, x1); + println!("reach here 2"); // Step 5: e1 = x1 == 0 let e1 = fp_chip.is_equal(ctx, x1.clone(), zero_int); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index d28b515c..b133c9b6 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -122,8 +122,8 @@ mod test { .lookup_bits(19) .expect_satisfied(true) .run(|ctx, range| { - let fp_chip = FpChip::::new(range, 88, 3); - let fq_chip = FqChip::::new(range, 88, 3); + let fp_chip = FpChip::::new(range, 64, 4); + let fq_chip = FqChip::::new(range, 64, 4); let ecc_chip = EccChip::>::new(&fp_chip); let sha256_chip = Sha256Chip::new(range); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index 4da4e2ac..408d90fc 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -1,3 +1,5 @@ +use std::ops::{ Mul, Rem }; + use halo2_base::{ gates::{ GateInstructions, RangeChip, RangeInstructions }, utils::{ fe_to_biguint, BigPrimeField }, @@ -6,8 +8,9 @@ use halo2_base::{ QuantumCell, }; use itertools::Itertools; -use num_bigint::{ BigUint, ToBigInt }; -use num_traits::Pow; +use num_bigint::{ BigInt, BigUint, ToBigInt }; +use num_integer::Integer; +use num_traits::{ One, Pow, Zero }; use crate::{ bigint::{ CRTInteger, OverflowInteger, ProperCrtUint }, @@ -15,6 +18,7 @@ use crate::{ secp256k1::{ util::{ bits_le_to_fe_assigned, fe_to_bits_le }, FpChip }, }; +// Assumes that input is a byte pub(crate) fn byte_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, @@ -75,10 +79,10 @@ pub(crate) fn limbs_le_to_bigint( ) -> ProperCrtUint { let mut value = BigUint::from(0u64); for i in 0..limbs.len() { - value += (BigUint::from(1u64) << (88 * i)) * fe_to_biguint(limbs[i].value()); + value += (BigUint::from(1u64) << (64 * i)) * fe_to_biguint(limbs[i].value()); } - let assigned_uint = OverflowInteger::new(limbs.to_vec(), 88); + let assigned_uint = OverflowInteger::new(limbs.to_vec(), 64); let assigned_native = OverflowInteger::evaluate_native( ctx, fp_chip.range().gate(), @@ -87,7 +91,7 @@ pub(crate) fn limbs_le_to_bigint( ); let assigned_uint = CRTInteger::new(assigned_uint, assigned_native, value.to_bigint().unwrap()); - ProperCrtUint(assigned_uint) + fp_chip.carry_mod(ctx, assigned_uint) } pub(crate) fn mod_inverse( @@ -102,11 +106,10 @@ pub(crate) fn mod_inverse( let p_minus_two = p.clone() - 2u64; let num_native = num.value(); - let inverse_native = num_native.clone().pow(p_minus_two); - let mod_inverse_native = inverse_native % p; - assert_eq!(num_native * mod_inverse_native.clone(), BigUint::from(1u64)); + let inverse_native = num_native.modpow(&p_minus_two, &p); + assert_eq!((num_native * inverse_native.clone()) % p, BigUint::from(1u64)); - let mod_inverse = fp_chip.load_constant_uint(ctx, mod_inverse_native); + let mod_inverse = fp_chip.load_constant_uint(ctx, inverse_native); let is_one = fp_chip.mul(ctx, num, mod_inverse.clone()); let is_equal = fp_chip.is_equal(ctx, is_one, one_int); ctx.constrain_equal(&is_equal, &one); From 2d4adaee4c1afe4145a6ea1969f29fdb24c3baa9 Mon Sep 17 00:00:00 2001 From: shryasss Date: Tue, 13 Feb 2024 12:20:33 +0530 Subject: [PATCH 08/24] chore: code cleanup --- .../src/secp256k1/hash_to_curve/constants.rs | 63 +++++++++---------- .../hash_to_curve/expand_message_xmd.rs | 14 +++-- .../secp256k1/hash_to_curve/hash_to_field.rs | 54 +++++++++------- .../src/secp256k1/hash_to_curve/iso_map.rs | 2 - .../secp256k1/hash_to_curve/map_to_curve.rs | 28 +++++++-- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 25 ++++---- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 32 +--------- 7 files changed, 109 insertions(+), 109 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index 514ad2e3..25656354 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -1,9 +1,6 @@ use halo2_base::{ gates::RangeChip, utils::BigPrimeField, AssignedValue, Context }; -use num_bigint::BigUint; -use num_integer::div_ceil; -use num_traits::Num; use crate::{ bigint::ProperCrtUint, secp256k1::FpChip }; -use super::util::limbs_le_to_bigint; +use super::util::limbs_le_to_bn; pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { let zero = ctx.load_zero(); @@ -39,10 +36,10 @@ pub(crate) fn get_Z( 18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615, ] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, z.as_slice()) + limbs_le_to_bn(ctx, fp_chip, z.as_slice()) } // A = 28734576633528757162648956269730739219262246272443394170905244663053633733939 @@ -56,7 +53,7 @@ pub(crate) fn get_A( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, a.as_slice()) + limbs_le_to_bn(ctx, fp_chip, a.as_slice()) } pub(crate) fn get_B( @@ -69,7 +66,7 @@ pub(crate) fn get_B( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, b.as_slice()) + limbs_le_to_bn(ctx, fp_chip, b.as_slice()) } pub(crate) fn get_C1( @@ -82,7 +79,7 @@ pub(crate) fn get_C1( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, c1.as_slice()) + limbs_le_to_bn(ctx, fp_chip, c1.as_slice()) } pub(crate) fn get_C2( @@ -95,7 +92,7 @@ pub(crate) fn get_C2( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, c2.as_slice()) + limbs_le_to_bn(ctx, fp_chip, c2.as_slice()) } // k_(1,0) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7 @@ -109,7 +106,7 @@ pub(crate) fn get_k_1_0( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(1,1) = 0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581 @@ -123,7 +120,7 @@ pub(crate) fn get_k_1_1( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(1,2) = 0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262 @@ -137,7 +134,7 @@ pub(crate) fn get_k_1_2( .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(1,3) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c @@ -148,10 +145,10 @@ pub(crate) fn get_k_1_3( ) -> ProperCrtUint { let k = [10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(2,0) = 0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b @@ -162,10 +159,10 @@ pub(crate) fn get_k_2_0( ) -> ProperCrtUint { let k = [11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(2,1) = 0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14 @@ -176,10 +173,10 @@ pub(crate) fn get_k_2_1( ) -> ProperCrtUint { let k = [14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(3,0) = 0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c @@ -190,10 +187,10 @@ pub(crate) fn get_k_3_0( ) -> ProperCrtUint { let k = [11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(3,1) = 0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3 @@ -204,10 +201,10 @@ pub(crate) fn get_k_3_1( ) -> ProperCrtUint { let k = [16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(3,2) = 0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931 @@ -218,10 +215,10 @@ pub(crate) fn get_k_3_2( ) -> ProperCrtUint { let k = [12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(3,3) = 0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84 @@ -232,10 +229,10 @@ pub(crate) fn get_k_3_3( ) -> ProperCrtUint { let k = [9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(4,0) = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b @@ -248,10 +245,10 @@ pub(crate) fn get_k_4_0( 18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615, ] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(4,1) = 0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573 @@ -262,10 +259,10 @@ pub(crate) fn get_k_4_1( ) -> ProperCrtUint { let k = [16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } // k_(4,2) = 0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f @@ -276,8 +273,8 @@ pub(crate) fn get_k_4_2( ) -> ProperCrtUint { let k = [12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116] .iter() - .map(|v| ctx.load_witness(F::from(*v))) + .map(|v| ctx.load_constant(F::from(*v))) .collect::>(); - limbs_le_to_bigint(ctx, range, fp_chip, k.as_slice()) + limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index 58c6d428..79ff926b 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -5,9 +5,7 @@ use halo2_base::{ Context, QuantumCell, }; - use crate::secp256k1::sha256::Sha256Chip; - use super::{ constants::{ get_dst_prime, get_lib_str, get_z_pad }, util::{ bits_le_to_bytes_assigned, bytes_to_bits_le_assigned }, @@ -27,9 +25,8 @@ fn msg_prime( let lib_str = get_lib_str(ctx); let dst_prime = get_dst_prime(ctx); - let mut msg_prime = Vec::>::with_capacity( - calc_msg_prime_output_length(msg_bytes.len()) - ); + let msg_prime_len = calc_msg_prime_output_length(msg_bytes.len()); + let mut msg_prime = Vec::>::with_capacity(msg_prime_len); // msg_prme = z_pad ... msg_prime.extend(z_pad); @@ -46,6 +43,7 @@ fn msg_prime( // msg_prme = z_pad || msg || lib_str || 0 || dst_prime msg_prime.extend(dst_prime); + assert_eq!(msg_prime.len(), msg_prime_len); msg_prime } @@ -67,6 +65,9 @@ fn hash_bi( b0_bytes: &[AssignedValue], bi_minus_one_bytes: &[AssignedValue] ) -> Vec> { + assert_eq!(b0_bytes.len(), 32); + assert_eq!(b0_bytes.len(), bi_minus_one_bytes.len()); + let b0_bits = bytes_to_bits_le_assigned(ctx, range, b0_bytes); let bi_minus_one_bits = bytes_to_bits_le_assigned(ctx, range, bi_minus_one_bytes); @@ -84,6 +85,9 @@ fn hash_b( b_idx_byte: &AssignedValue, b_bytes: &Vec> ) -> Vec> { + assert_eq!(b_bytes.len(), 32); + assert_eq!(b_idx_byte.value() < &F::from(8u64), true); + let dst_prime = get_dst_prime(ctx); let mut preimage = Vec::>::new(); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index c463ccc4..83e1bb3a 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -7,34 +7,18 @@ use halo2_base::{ }; use num_bigint::BigUint; use num_integer::div_ceil; - use crate::{ bigint::ProperCrtUint, fields::FieldChip, - secp256k1::{ hash_to_curve::util::limbs_le_to_bigint, sha256::Sha256Chip, FpChip }, + secp256k1::{ hash_to_curve::util::limbs_le_to_bn, sha256::Sha256Chip, FpChip }, }; - use super::expand_message_xmd::expand_message_xmd; -pub(crate) fn hash_to_field( - ctx: &mut Context, - fp_chip: &FpChip<'_, F>, - sha256_chip: &Sha256Chip, - msg_bytes: &[AssignedValue] -) -> (ProperCrtUint, ProperCrtUint) { - let expanded_msg_bytes = expand_message_xmd(ctx, fp_chip.range, sha256_chip, msg_bytes); - - let u0 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[0..48]); - let u1 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[48..96]); - - (u0, u1) -} - -fn bytes_to_registers( +fn bytes_le_to_limbs( ctx: &mut Context, fp_chip: &FpChip<'_, F>, bytes: &[AssignedValue] -) -> ProperCrtUint { +) -> Vec> { let mut limbs = Vec::>::with_capacity(div_ceil(bytes.len(), 8)); for chunk in bytes.chunks(8) { let mut limb = ctx.load_zero(); @@ -50,15 +34,26 @@ fn bytes_to_registers( limbs.push(limb); } + limbs +} + +fn bytes_to_registers( + ctx: &mut Context, + fp_chip: &FpChip<'_, F>, + bytes: &[AssignedValue] +) -> ProperCrtUint { + let limbs = bytes_le_to_limbs(ctx, fp_chip, bytes); + let mut lo_limbs = limbs[..3].to_vec(); lo_limbs.push(ctx.load_zero()); + let mut hi_limbs = limbs[3..].to_vec(); hi_limbs.push(ctx.load_zero()); - let lo = limbs_le_to_bigint(ctx, fp_chip.range(), fp_chip, lo_limbs.as_slice()); - let hi = limbs_le_to_bigint(ctx, fp_chip.range(), fp_chip, hi_limbs.as_slice()); + let lo = limbs_le_to_bn(ctx, fp_chip, lo_limbs.as_slice()); + let hi = limbs_le_to_bn(ctx, fp_chip, hi_limbs.as_slice()); - let two_power_192 = fp_chip.load_constant_uint(ctx, BigUint::from(1u64) << 192); + let two_power_192 = fp_chip.load_constant_uint(ctx, BigUint::from(2u8).pow(192)); let num = fp_chip.mul_no_carry(ctx, hi, two_power_192); let num = fp_chip.add_no_carry(ctx, num, lo); @@ -66,3 +61,18 @@ fn bytes_to_registers( num } + +pub(crate) fn hash_to_field( + ctx: &mut Context, + fp_chip: &FpChip<'_, F>, + sha256_chip: &Sha256Chip, + msg_bytes: &[AssignedValue] +) -> (ProperCrtUint, ProperCrtUint) { + let expanded_msg_bytes = expand_message_xmd(ctx, fp_chip.range, sha256_chip, msg_bytes); + assert_eq!(expanded_msg_bytes.len(), 96); + + let u0 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[0..48]); + let u1 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[48..96]); + + (u0, u1) +} diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs index 25f60d3d..2e723bc1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -1,7 +1,5 @@ use halo2_base::{ utils::BigPrimeField, Context }; - use crate::{ bigint::ProperCrtUint, fields::FieldChip, secp256k1::FpChip }; - use super::constants::{ get_k_1_0, get_k_1_1, diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 563e04b0..942e6728 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -10,8 +10,6 @@ use crate::{ }, }; -use super::util::mod_inverse; - fn xy2_selector( ctx: &mut Context, fp_chip: &FpChip<'_, F>, @@ -22,7 +20,7 @@ fn xy2_selector( x1: ProperCrtUint, x2: ProperCrtUint ) -> (ProperCrtUint, ProperCrtUint) { - let gate = fp_chip.range.gate(); + let gate = fp_chip.range().gate(); let one = ctx.load_constant(F::ONE); let sq_gx1_sqrt = fp_chip.mul(ctx, gx1_sqrt.clone(), gx1_sqrt); @@ -40,6 +38,29 @@ fn xy2_selector( (x, y2) } +fn mod_inverse( + ctx: &mut Context, + fp_chip: &FpChip<'_, F>, + num: ProperCrtUint +) -> ProperCrtUint { + let one = ctx.load_constant(F::ONE); + let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); + + let p = fp_chip.p.to_biguint().unwrap(); + let p_minus_two = p.clone() - 2u64; + + let num_native = num.value(); + let inverse_native = num_native.modpow(&p_minus_two, &p); + assert_eq!((num_native * inverse_native.clone()) % p, BigUint::from(1u64)); + + let mod_inverse = fp_chip.load_constant_uint(ctx, inverse_native); + let is_one = fp_chip.mul(ctx, num, mod_inverse.clone()); + let is_equal = fp_chip.is_equal(ctx, is_one, one_int); + ctx.constrain_equal(&is_equal, &one); + + mod_inverse +} + pub(crate) fn map_to_curve( ctx: &mut Context, fp_chip: &FpChip<'_, F>, @@ -53,7 +74,6 @@ pub(crate) fn map_to_curve( let range = fp_chip.range(); let gate = range.gate(); - let zero = ctx.load_zero(); let one = ctx.load_constant(F::ONE); let zero_int = fp_chip.load_constant_uint(ctx, BigUint::from(0u64)); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index b133c9b6..b5a3d012 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -84,42 +84,41 @@ mod test { #[test] fn test_hash_to_curve() { - // msg = "abc" - let msg = vec![97u64, 98u64, 99u64]; + let msg = b"abcdef0123456789"; let q0_gx1_sqrt = ::ScalarExt::from([ - 1664545361815120357u64, 10283872013620121914u64, 9380010581010034654u64, 4261145792225450732u64, + 8436907082510902807u64, 16481306271273964905u64, 12340693169241754123u64, 5840290864233247061u64, ]); let q0_gx2_sqrt = ::ScalarExt::from([ 1u64, 0u64, 0u64, 0u64, ]); let q0_y_pos = ::ScalarExt::from([ - 1664545361815120357u64, 10283872013620121914u64, 9380010581010034654u64, 4261145792225450732u64, + 8436907082510902807u64, 16481306271273964905u64, 12340693169241754123u64, 5840290864233247061u64, ]); let q0_x_mapped = ::ScalarExt::from([ - 5925487804738118359u64, 4856574525535083224u64, 12797074899347248930u64, 566772074147120223u64, + 1666473185380682589u64, 5940335290811295862u64, 16073821616946219607u64, 6299765855519516506u64, ]); let q0_y_mapped = ::ScalarExt::from([ - 4617496280555238207u64, 14690993926117989357u64, 3636581750055392523u64, 6937101362475356158u64, + 14183132322842682307u64, 3799824159173722014u64, 17680812620347148404u64, 7222729814779291343u64, ]); let q1_gx1_sqrt = ::ScalarExt::from([ - 7355280221998350180u64, 4783425048112263089u64, 5071308975172430165u64, 3916832897263395160u64, + 909194377947652581u64, 9506023292142230081u64, 13109065517192500057u64, 2140988711709947970u64, ]); let q1_gx2_sqrt = ::ScalarExt::from([ 1u64, 0u64, 0u64, 0u64, ]); let q1_y_pos = ::ScalarExt::from([ - 7355280221998350180u64, 4783425048112263089u64, 5071308975172430165u64, 3916832897263395160u64, + 909194377947652581u64, 9506023292142230081u64, 13109065517192500057u64, 2140988711709947970u64, ]); let q1_x_mapped = ::ScalarExt::from([ - 13296707460026998648u64, 318503968633800990u64, 15989839026330281858u64, 16856858595694562935u64, + 15496950058064191480u64, 16608196343028055450u64, 6698082460314400323u64, 17914594903168254206u64, ]); let q1_y_mapped = ::ScalarExt::from([ - 1338026386978707379u64, 6209856281762218480u64, 13772974005733639516u64, 14629888772142879508u64, + 17158098838744772439u64, 14635829310764858396u64, 7975190798015443370u64, 12914166355471935767u64, ]); base_test() - .k(20) - .lookup_bits(19) + .k(15) + .lookup_bits(14) .expect_satisfied(true) .run(|ctx, range| { let fp_chip = FpChip::::new(range, 64, 4); @@ -130,7 +129,7 @@ mod test { let msg_bytes = msg .iter() - .map(|&x| ctx.load_witness(Fr::from(x))) + .map(|&x| ctx.load_witness(Fr::from(x as u64))) .collect::>(); let q0_gx1_sqrt = fq_chip.load_private(ctx, q0_gx1_sqrt); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index 408d90fc..66ac239d 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -1,5 +1,3 @@ -use std::ops::{ Mul, Rem }; - use halo2_base::{ gates::{ GateInstructions, RangeChip, RangeInstructions }, utils::{ fe_to_biguint, BigPrimeField }, @@ -8,9 +6,7 @@ use halo2_base::{ QuantumCell, }; use itertools::Itertools; -use num_bigint::{ BigInt, BigUint, ToBigInt }; -use num_integer::Integer; -use num_traits::{ One, Pow, Zero }; +use num_bigint::{ BigUint, ToBigInt }; use crate::{ bigint::{ CRTInteger, OverflowInteger, ProperCrtUint }, @@ -71,9 +67,8 @@ pub(crate) fn bits_le_to_bytes_assigned( .collect_vec() } -pub(crate) fn limbs_le_to_bigint( +pub(crate) fn limbs_le_to_bn( ctx: &mut Context, - range: &RangeChip, fp_chip: &FpChip<'_, F>, limbs: &[AssignedValue] ) -> ProperCrtUint { @@ -93,26 +88,3 @@ pub(crate) fn limbs_le_to_bigint( fp_chip.carry_mod(ctx, assigned_uint) } - -pub(crate) fn mod_inverse( - ctx: &mut Context, - fp_chip: &FpChip<'_, F>, - num: ProperCrtUint -) -> ProperCrtUint { - let one = ctx.load_constant(F::ONE); - let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); - - let p = fp_chip.p.to_biguint().unwrap(); - let p_minus_two = p.clone() - 2u64; - - let num_native = num.value(); - let inverse_native = num_native.modpow(&p_minus_two, &p); - assert_eq!((num_native * inverse_native.clone()) % p, BigUint::from(1u64)); - - let mod_inverse = fp_chip.load_constant_uint(ctx, inverse_native); - let is_one = fp_chip.mul(ctx, num, mod_inverse.clone()); - let is_equal = fp_chip.is_equal(ctx, is_one, one_int); - ctx.constrain_equal(&is_equal, &one); - - mod_inverse -} From b24d10367a72d3210e63045fb161866c784b887a Mon Sep 17 00:00:00 2001 From: shryasss Date: Wed, 14 Feb 2024 07:43:40 +0530 Subject: [PATCH 09/24] fix: hash_to_curve w/o precompute values --- .../src/secp256k1/hash_to_curve/constants.rs | 97 +++++------- .../hash_to_curve/expand_message_xmd.rs | 37 ++--- .../secp256k1/hash_to_curve/hash_to_field.rs | 38 ++--- .../src/secp256k1/hash_to_curve/iso_map.rs | 84 ++++------ .../secp256k1/hash_to_curve/map_to_curve.rs | 77 ++++++---- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 145 +++--------------- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 45 +++--- halo2-ecc/src/secp256k1/sha256/mod.rs | 100 ++++++------ 8 files changed, 238 insertions(+), 385 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index 25656354..8349de11 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -1,6 +1,6 @@ -use halo2_base::{ gates::RangeChip, utils::BigPrimeField, AssignedValue, Context }; -use crate::{ bigint::ProperCrtUint, secp256k1::FpChip }; use super::util::limbs_le_to_bn; +use crate::{bigint::ProperCrtUint, secp256k1::FpChip}; +use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { let zero = ctx.load_zero(); @@ -15,29 +15,23 @@ pub(crate) fn get_lib_str(ctx: &mut Context) -> Vec(ctx: &mut Context) -> Vec> { let dst_prime = [ - 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, 99, - 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, 87, - 85, 95, 82, 79, 95, 49, + 81, 85, 85, 88, 45, 86, 48, 49, 45, 67, 83, 48, 50, 45, 119, 105, 116, 104, 45, 115, 101, + 99, 112, 50, 53, 54, 107, 49, 95, 88, 77, 68, 58, 83, 72, 65, 45, 50, 53, 54, 95, 83, 83, + 87, 85, 95, 82, 79, 95, 49, ]; - dst_prime - .into_iter() - .map(F::from) - .map(|v| ctx.load_constant(v)) - .collect::>() + dst_prime.into_iter().map(F::from).map(|v| ctx.load_constant(v)).collect::>() } // Z = 115792089237316195423570985008687907853269984665640564039457584007908834671652 pub(crate) fn get_Z( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let z = [ - 18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615, - ] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); + let z = + [18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); limbs_le_to_bn(ctx, fp_chip, z.as_slice()) } @@ -45,8 +39,7 @@ pub(crate) fn get_Z( // A = 28734576633528757162648956269730739219262246272443394170905244663053633733939 pub(crate) fn get_A( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let a = [4635408806871057715, 16813014259472469597, 11568152433342665330, 4577682160469023452] .iter() @@ -58,21 +51,16 @@ pub(crate) fn get_A( pub(crate) fn get_B( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let b = [1771, 0, 0, 0] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); + let b = [1771, 0, 0, 0].iter().map(|v| ctx.load_constant(F::from(*v))).collect::>(); limbs_le_to_bn(ctx, fp_chip, b.as_slice()) } pub(crate) fn get_C1( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let c1 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994] .iter() @@ -84,8 +72,7 @@ pub(crate) fn get_C1( pub(crate) fn get_C2( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804] .iter() @@ -98,8 +85,7 @@ pub(crate) fn get_C2( // k_(1,0) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7 pub(crate) fn get_k_1_0( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008] .iter() @@ -112,8 +98,7 @@ pub(crate) fn get_k_1_0( // k_(1,1) = 0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581 pub(crate) fn get_k_1_1( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237] .iter() @@ -126,8 +111,7 @@ pub(crate) fn get_k_1_1( // k_(1,2) = 0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262 pub(crate) fn get_k_1_2( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894] .iter() @@ -140,8 +124,7 @@ pub(crate) fn get_k_1_2( // k_(1,3) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c pub(crate) fn get_k_1_3( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008] .iter() @@ -154,8 +137,7 @@ pub(crate) fn get_k_1_3( // k_(2,0) = 0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b pub(crate) fn get_k_2_0( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418] .iter() @@ -168,8 +150,7 @@ pub(crate) fn get_k_2_0( // k_(2,1) = 0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14 pub(crate) fn get_k_2_1( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821] .iter() @@ -182,8 +163,7 @@ pub(crate) fn get_k_2_1( // k_(3,0) = 0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c pub(crate) fn get_k_3_0( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071] .iter() @@ -196,8 +176,7 @@ pub(crate) fn get_k_3_0( // k_(3,1) = 0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3 pub(crate) fn get_k_3_1( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615] .iter() @@ -210,8 +189,7 @@ pub(crate) fn get_k_3_1( // k_(3,2) = 0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931 pub(crate) fn get_k_3_2( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947] .iter() @@ -224,8 +202,7 @@ pub(crate) fn get_k_3_2( // k_(3,3) = 0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84 pub(crate) fn get_k_3_3( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669] .iter() @@ -238,15 +215,13 @@ pub(crate) fn get_k_3_3( // k_(4,0) = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b pub(crate) fn get_k_4_0( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [ - 18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615, - ] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); + let k = + [18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615] + .iter() + .map(|v| ctx.load_constant(F::from(*v))) + .collect::>(); limbs_le_to_bn(ctx, fp_chip, k.as_slice()) } @@ -254,8 +229,7 @@ pub(crate) fn get_k_4_0( // k_(4,1) = 0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573 pub(crate) fn get_k_4_1( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023] .iter() @@ -268,8 +242,7 @@ pub(crate) fn get_k_4_1( // k_(4,2) = 0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f pub(crate) fn get_k_4_2( ctx: &mut Context, - range: &RangeChip, - fp_chip: &FpChip<'_, F> + fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { let k = [12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116] .iter() diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index 79ff926b..57a7e7f1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -1,14 +1,12 @@ -use halo2_base::{ - gates::{ GateInstructions, RangeChip, RangeInstructions }, - utils::BigPrimeField, - AssignedValue, - Context, - QuantumCell, +use super::{ + constants::{get_dst_prime, get_lib_str, get_z_pad}, + util::{bits_le_to_bytes_assigned, bytes_to_bits_le_assigned}, }; use crate::secp256k1::sha256::Sha256Chip; -use super::{ - constants::{ get_dst_prime, get_lib_str, get_z_pad }, - util::{ bits_le_to_bytes_assigned, bytes_to_bits_le_assigned }, +use halo2_base::{ + gates::{GateInstructions, RangeChip, RangeInstructions}, + utils::BigPrimeField, + AssignedValue, Context, QuantumCell, }; fn calc_msg_prime_output_length(msg_length: usize) -> usize { @@ -17,7 +15,7 @@ fn calc_msg_prime_output_length(msg_length: usize) -> usize { fn msg_prime( ctx: &mut Context, - msg_bytes: &[AssignedValue] + msg_bytes: &[AssignedValue], ) -> Vec> { let zero = ctx.load_zero(); @@ -50,10 +48,10 @@ fn msg_prime( fn hash_msg_prime_to_b0( ctx: &mut Context, sha256_chip: &Sha256Chip<'_, F>, - msg_prime_bytes: &[AssignedValue] + msg_prime_bytes: &[AssignedValue], ) -> Vec> { let msg_prime_bytes = msg_prime_bytes.iter().map(|byte| QuantumCell::Existing(*byte)); - let hash = sha256_chip.digest_le(ctx, msg_prime_bytes).unwrap(); + let hash = sha256_chip.digest(ctx, msg_prime_bytes).unwrap(); hash } @@ -63,7 +61,7 @@ fn hash_bi( sha256_chip: &Sha256Chip, b_idx_byte: &AssignedValue, b0_bytes: &[AssignedValue], - bi_minus_one_bytes: &[AssignedValue] + bi_minus_one_bytes: &[AssignedValue], ) -> Vec> { assert_eq!(b0_bytes.len(), 32); assert_eq!(b0_bytes.len(), bi_minus_one_bytes.len()); @@ -83,7 +81,7 @@ fn hash_b( ctx: &mut Context, sha256_chip: &Sha256Chip<'_, F>, b_idx_byte: &AssignedValue, - b_bytes: &Vec> + b_bytes: &Vec>, ) -> Vec> { assert_eq!(b_bytes.len(), 32); assert_eq!(b_idx_byte.value() < &F::from(8u64), true); @@ -96,7 +94,7 @@ fn hash_b( preimage.extend(dst_prime); let preimage = preimage.iter().map(|byte| QuantumCell::Existing(*byte)); - let hash = sha256_chip.digest_le(ctx, preimage).unwrap(); + let hash = sha256_chip.digest(ctx, preimage).unwrap(); hash } @@ -105,7 +103,7 @@ fn str_xor( ctx: &mut Context, range: &RangeChip, a_bits: &[AssignedValue], - b_bits: &[AssignedValue] + b_bits: &[AssignedValue], ) -> Vec> { assert_eq!(a_bits.len(), b_bits.len()); @@ -124,7 +122,7 @@ pub(crate) fn expand_message_xmd( ctx: &mut Context, range: &RangeChip, sha256_chip: &Sha256Chip, - msg_bytes: &[AssignedValue] + msg_bytes: &[AssignedValue], ) -> Vec> { let one = ctx.load_constant(F::from(1)); let two = ctx.load_constant(F::from(2)); @@ -136,5 +134,8 @@ pub(crate) fn expand_message_xmd( let b2 = hash_bi(ctx, range, sha256_chip, &two, &b0, &b1); let b3 = hash_bi(ctx, range, sha256_chip, &three, &b0, &b2); - [b1, b2, b3].concat() + let mut expanded_msg = [b1, b2, b3].concat(); + expanded_msg.reverse(); + + expanded_msg } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index 83e1bb3a..16d097ce 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -1,23 +1,21 @@ +use super::expand_message_xmd::expand_message_xmd; +use crate::{ + bigint::ProperCrtUint, + fields::FieldChip, + secp256k1::{hash_to_curve::util::limbs_le_to_bn, sha256::Sha256Chip, FpChip}, +}; use halo2_base::{ - gates::{ GateInstructions, RangeInstructions }, + gates::{GateInstructions, RangeInstructions}, utils::BigPrimeField, - AssignedValue, - Context, - QuantumCell, + AssignedValue, Context, QuantumCell, }; use num_bigint::BigUint; use num_integer::div_ceil; -use crate::{ - bigint::ProperCrtUint, - fields::FieldChip, - secp256k1::{ hash_to_curve::util::limbs_le_to_bn, sha256::Sha256Chip, FpChip }, -}; -use super::expand_message_xmd::expand_message_xmd; fn bytes_le_to_limbs( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - bytes: &[AssignedValue] + bytes: &[AssignedValue], ) -> Vec> { let mut limbs = Vec::>::with_capacity(div_ceil(bytes.len(), 8)); for chunk in bytes.chunks(8) { @@ -26,10 +24,12 @@ fn bytes_le_to_limbs( if chunk.len() < 8 && i >= chunk.len() { break; } - limb = fp_chip - .range() - .gate() - .mul_add(ctx, chunk[i], QuantumCell::Constant(F::from(1 << (8 * i))), limb); + limb = fp_chip.range().gate().mul_add( + ctx, + chunk[i], + QuantumCell::Constant(F::from(1 << (8 * i))), + limb, + ); } limbs.push(limb); } @@ -40,7 +40,7 @@ fn bytes_le_to_limbs( fn bytes_to_registers( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - bytes: &[AssignedValue] + bytes: &[AssignedValue], ) -> ProperCrtUint { let limbs = bytes_le_to_limbs(ctx, fp_chip, bytes); @@ -66,13 +66,13 @@ pub(crate) fn hash_to_field( ctx: &mut Context, fp_chip: &FpChip<'_, F>, sha256_chip: &Sha256Chip, - msg_bytes: &[AssignedValue] + msg_bytes: &[AssignedValue], ) -> (ProperCrtUint, ProperCrtUint) { let expanded_msg_bytes = expand_message_xmd(ctx, fp_chip.range, sha256_chip, msg_bytes); assert_eq!(expanded_msg_bytes.len(), 96); - let u0 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[0..48]); - let u1 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[48..96]); + let u1 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[0..48]); + let u0 = bytes_to_registers(ctx, fp_chip, &expanded_msg_bytes[48..96]); (u0, u1) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs index 2e723bc1..405abacc 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -1,34 +1,21 @@ -use halo2_base::{ utils::BigPrimeField, Context }; -use crate::{ bigint::ProperCrtUint, fields::FieldChip, secp256k1::FpChip }; use super::constants::{ - get_k_1_0, - get_k_1_1, - get_k_1_2, - get_k_1_3, - get_k_2_0, - get_k_2_1, - get_k_3_0, - get_k_3_1, - get_k_3_2, - get_k_3_3, - get_k_4_0, - get_k_4_1, - get_k_4_2, + get_k_1_0, get_k_1_1, get_k_1_2, get_k_1_3, get_k_2_0, get_k_2_1, get_k_3_0, get_k_3_1, + get_k_3_2, get_k_3_3, get_k_4_0, get_k_4_1, get_k_4_2, }; +use crate::{bigint::ProperCrtUint, fields::FieldChip, secp256k1::FpChip}; +use halo2_base::{utils::BigPrimeField, Context}; fn x_num( ctx: &mut Context, fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint + x_3: ProperCrtUint, ) -> ProperCrtUint { - let range = fp_chip.range(); - - let k_1_3 = get_k_1_3(ctx, range, fp_chip); - let k_1_2 = get_k_1_2(ctx, range, fp_chip); - let k_1_1 = get_k_1_1(ctx, range, fp_chip); - let k_1_0 = get_k_1_0(ctx, range, fp_chip); + let k_1_3 = get_k_1_3(ctx, fp_chip); + let k_1_2 = get_k_1_2(ctx, fp_chip); + let k_1_1 = get_k_1_1(ctx, fp_chip); + let k_1_0 = get_k_1_0(ctx, fp_chip); // Step 1: a = k_(1,3) * x'^3 let a = fp_chip.mul(ctx, k_1_3, x_3); @@ -58,12 +45,10 @@ fn x_den( ctx: &mut Context, fp_chip: &FpChip<'_, F>, x: ProperCrtUint, - x_2: ProperCrtUint + x_2: ProperCrtUint, ) -> ProperCrtUint { - let range = fp_chip.range(); - - let k_2_0 = get_k_2_0(ctx, range, fp_chip); - let k_2_1 = get_k_2_1(ctx, range, fp_chip); + let k_2_0 = get_k_2_0(ctx, fp_chip); + let k_2_1 = get_k_2_1(ctx, fp_chip); // Step 1: a = x_2 + k_2_0 let a = fp_chip.add_no_carry(ctx, x_2, k_2_0); @@ -84,14 +69,12 @@ fn y_num( fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint + x_3: ProperCrtUint, ) -> ProperCrtUint { - let range = fp_chip.range(); - - let k_3_3 = get_k_3_3(ctx, range, fp_chip); - let k_3_2 = get_k_3_2(ctx, range, fp_chip); - let k_3_1 = get_k_3_1(ctx, range, fp_chip); - let k_3_0 = get_k_3_0(ctx, range, fp_chip); + let k_3_3 = get_k_3_3(ctx, fp_chip); + let k_3_2 = get_k_3_2(ctx, fp_chip); + let k_3_1 = get_k_3_1(ctx, fp_chip); + let k_3_0 = get_k_3_0(ctx, fp_chip); // Step 1: a = k_3_3 * x_3 let a = fp_chip.mul(ctx, k_3_3, x_3); @@ -122,13 +105,11 @@ fn y_den( fp_chip: &FpChip<'_, F>, x: ProperCrtUint, x_2: ProperCrtUint, - x_3: ProperCrtUint + x_3: ProperCrtUint, ) -> ProperCrtUint { - let range = fp_chip.range(); - - let k_4_0 = get_k_4_0(ctx, range, fp_chip); - let k_4_1 = get_k_4_1(ctx, range, fp_chip); - let k_4_2 = get_k_4_2(ctx, range, fp_chip); + let k_4_0 = get_k_4_0(ctx, fp_chip); + let k_4_1 = get_k_4_1(ctx, fp_chip); + let k_4_2 = get_k_4_2(ctx, fp_chip); // Step 1: a = x_3 + k_4_0 let a = fp_chip.add_no_carry(ctx, x_3, k_4_0); @@ -156,11 +137,7 @@ pub(crate) fn iso_map( fp_chip: &FpChip<'_, F>, x: ProperCrtUint, y: ProperCrtUint, - x_mapped: ProperCrtUint, - y_mapped: ProperCrtUint -) { - let one = ctx.load_constant(F::ONE); - +) -> (ProperCrtUint, ProperCrtUint) { // Step 1: calculate x^2 let x_2 = fp_chip.mul(ctx, x.clone(), x.clone()); @@ -179,18 +156,9 @@ pub(crate) fn iso_map( // Step 6: calculate y_den let y_den = y_den(ctx, fp_chip, x, x_2, x_3); - // Step 7: x_mapped * x_den === x_num - let x_check = fp_chip.mul(ctx, x_mapped, x_den); - - // Step 8: y_mapped = y' * y_num / y_den - // y_mapped * y_den === y' * y_num - let y_check = fp_chip.mul(ctx, y_mapped, y_den); - - let y_check_2 = fp_chip.mul(ctx, y, y_num); + let x_mapped = fp_chip.divide(ctx, x_num.clone(), x_den.clone()); + let y_mapped = fp_chip.divide(ctx, y_num.clone(), y_den.clone()); + let y_mapped = fp_chip.mul(ctx, y_mapped, y.clone()); - // Ensure that the provided x_mapped and y_mapped values are correct - let check1 = fp_chip.is_equal(ctx, x_check, x_num); - ctx.constrain_equal(&check1, &one); - let check_2 = fp_chip.is_equal(ctx, y_check, y_check_2); - ctx.constrain_equal(&check_2, &one); + (x_mapped, y_mapped) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 942e6728..9e03c47b 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -1,11 +1,19 @@ -use halo2_base::{ gates::{ GateInstructions, RangeInstructions }, utils::BigPrimeField, Context }; +use halo2_base::{ + gates::{GateInstructions, RangeInstructions}, + halo2_proofs::halo2curves::secq256k1::Fq as Fp, + utils::{BigPrimeField, ScalarField}, + Context, +}; use num_bigint::BigUint; use crate::{ bigint::ProperCrtUint, - fields::{ FieldChip, Selectable }, + fields::{FieldChip, Selectable}, secp256k1::{ - hash_to_curve::{ constants::{ get_A, get_B, get_C1, get_C2, get_Z }, iso_map::iso_map }, + hash_to_curve::{ + constants::{get_A, get_B, get_C1, get_C2, get_Z}, + iso_map::iso_map, + }, FpChip, }, }; @@ -14,22 +22,24 @@ fn xy2_selector( ctx: &mut Context, fp_chip: &FpChip<'_, F>, gx1: ProperCrtUint, - gx1_sqrt: ProperCrtUint, gx2: ProperCrtUint, - gx2_sqrt: ProperCrtUint, x1: ProperCrtUint, - x2: ProperCrtUint + x2: ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { let gate = fp_chip.range().gate(); let one = ctx.load_constant(F::ONE); + let gx1_sqrt = sqrt(ctx, fp_chip, gx1.clone()); + let gx2_sqrt = sqrt(ctx, fp_chip, gx2.clone()); + let sq_gx1_sqrt = fp_chip.mul(ctx, gx1_sqrt.clone(), gx1_sqrt); let sq_gx2_sqrt = fp_chip.mul(ctx, gx2_sqrt.clone(), gx2_sqrt); - let s1 = fp_chip.is_equal(ctx, sq_gx1_sqrt, gx1.clone()); - let s2 = fp_chip.is_equal(ctx, sq_gx2_sqrt, gx2.clone()); + let s1 = fp_chip.is_equal(ctx, sq_gx1_sqrt.clone(), gx1.clone()); + let s2 = fp_chip.is_equal(ctx, sq_gx2_sqrt.clone(), gx2.clone()); let _one = gate.add(ctx, s1, s2); + assert_eq!(_one.value(), &F::ONE); ctx.constrain_equal(&_one, &one); let x = fp_chip.select(ctx, x1, x2, s1); @@ -41,7 +51,7 @@ fn xy2_selector( fn mod_inverse( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - num: ProperCrtUint + num: ProperCrtUint, ) -> ProperCrtUint { let one = ctx.load_constant(F::ONE); let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); @@ -56,20 +66,31 @@ fn mod_inverse( let mod_inverse = fp_chip.load_constant_uint(ctx, inverse_native); let is_one = fp_chip.mul(ctx, num, mod_inverse.clone()); let is_equal = fp_chip.is_equal(ctx, is_one, one_int); + assert_eq!(is_equal.value(), &F::ONE); ctx.constrain_equal(&is_equal, &one); mod_inverse } +pub(crate) fn sqrt( + ctx: &mut Context, + fp_chip: &FpChip<'_, F>, + num: ProperCrtUint, +) -> ProperCrtUint { + let p = fp_chip.p.to_biguint().unwrap(); + let p_plus_1 = p.clone() + 1u64; + let p_plus_1_by_4 = p_plus_1 / 4u64; + + let sqrt_native = num.value().modpow(&p_plus_1_by_4, &p); + let sqrt = fp_chip.load_private(ctx, Fp::from_bytes_le(&sqrt_native.to_bytes_le())); + + sqrt +} + pub(crate) fn map_to_curve( ctx: &mut Context, fp_chip: &FpChip<'_, F>, u: ProperCrtUint, - gx1_sqrt: ProperCrtUint, - gx2_sqrt: ProperCrtUint, - y_pos: ProperCrtUint, - x_mapped: ProperCrtUint, - y_mapped: ProperCrtUint ) -> (ProperCrtUint, ProperCrtUint) { let range = fp_chip.range(); let gate = range.gate(); @@ -81,7 +102,7 @@ pub(crate) fn map_to_curve( // Step 1: tv1 = Z * u^2 let u_sq = fp_chip.mul(ctx, u.clone(), u.clone()); - let z = get_Z(ctx, range, fp_chip); + let z = get_Z(ctx, fp_chip); let tv1 = fp_chip.mul(ctx, z, u_sq); // Step 2: tv2 = tv1^2 @@ -92,9 +113,7 @@ pub(crate) fn map_to_curve( let x1 = fp_chip.carry_mod(ctx, x1); // Step 4: x1 = inv0(x1) - println!("reach here 1"); let x1 = mod_inverse(ctx, fp_chip, x1); - println!("reach here 2"); // Step 5: e1 = x1 == 0 let e1 = fp_chip.is_equal(ctx, x1.clone(), zero_int); @@ -104,18 +123,18 @@ pub(crate) fn map_to_curve( let x1 = fp_chip.carry_mod(ctx, x1); // Step 7: x1 = e1 ? c2 : x1 - let c2 = get_C2(ctx, range, fp_chip); + let c2 = get_C2(ctx, fp_chip); let x1 = fp_chip.select(ctx, c2, x1, e1); // Step 8: x1 = x1 * c1 # x1 = (-B / A) * (1 + (1 / (Z^2 * u^4 + Z * u^2))) - let c1 = get_C1(ctx, range, fp_chip); + let c1 = get_C1(ctx, fp_chip); let x1 = fp_chip.mul(ctx, x1.clone(), c1); // Step 9: gx1 = x1^2 let gx1 = fp_chip.mul(ctx, x1.clone(), x1.clone()); // Step 10: gx1 = gx1 + A - let a = get_A(ctx, range, fp_chip); + let a = get_A(ctx, fp_chip); let gx1 = fp_chip.add_no_carry(ctx, gx1, a); let gx1 = fp_chip.carry_mod(ctx, gx1); @@ -123,7 +142,7 @@ pub(crate) fn map_to_curve( let gx1 = fp_chip.mul(ctx, gx1, x1.clone()); // Step 12: gx1 = gx1 + B # gx1 = g(x1) = x1^3 + A * x1 + B - let b = get_B(ctx, range, fp_chip); + let b = get_B(ctx, fp_chip); let gx1 = fp_chip.add_no_carry(ctx, gx1, b); let gx1 = fp_chip.carry_mod(ctx, gx1); @@ -140,23 +159,25 @@ pub(crate) fn map_to_curve( // e2 = is_square(gx1) // x = CMOV(x2, x1, e2) # If is_square(gx1), x = x1, else x = x2 // y2 = CMOV(gx2, gx1, e2) # If is_square(gx1), y2 = gx1, else y2 = gx2 - let (x, y2) = xy2_selector(ctx, fp_chip, gx1, gx1_sqrt, gx2, gx2_sqrt, x1, x2); + let (x, y2) = xy2_selector(ctx, fp_chip, gx1, gx2, x1, x2); // Step 19: y = sqrt(y2) - let y_pos_sq = fp_chip.mul(ctx, y_pos.clone(), y_pos.clone()); - let e2 = fp_chip.is_equal(ctx, y_pos_sq, y2); + let y = sqrt(ctx, fp_chip, y2.clone()); + let y_sq = fp_chip.mul(ctx, y.clone(), y.clone()); + let e2 = fp_chip.is_equal(ctx, y_sq, y2); + assert_eq!(e2.value(), &F::ONE); ctx.constrain_equal(&e2, &one); // Step 20: e3 = sgn0(u) == sgn0(y) # Fix sign of y let sgn_u = fp_chip.is_even(ctx, u); - let sgn_y = fp_chip.is_even(ctx, y_pos.clone()); + let sgn_y = fp_chip.is_even(ctx, y.clone()); let e3 = gate.is_equal(ctx, sgn_u, sgn_y); // Step 21: y = e3 ? y : -y - let neg_y_pos = fp_chip.negate(ctx, y_pos.clone()); - let y = fp_chip.select(ctx, y_pos, neg_y_pos, e3); + let neg_y = fp_chip.negate(ctx, y.clone()); + let y = fp_chip.select(ctx, y, neg_y, e3); - iso_map(ctx, fp_chip, x, y, x_mapped.clone(), y_mapped.clone()); + let (x_mapped, y_mapped) = iso_map(ctx, fp_chip, x.clone(), y.clone()); (x_mapped, y_mapped) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index b5a3d012..04badc86 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -1,10 +1,10 @@ -use halo2_base::{ utils::BigPrimeField, AssignedValue, Context }; +use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; -use crate::{ bigint::ProperCrtUint, ecc::EcPoint }; +use crate::{bigint::ProperCrtUint, ecc::EcPoint}; -use self::{ hash_to_field::hash_to_field, map_to_curve::map_to_curve }; +use self::{hash_to_field::hash_to_field, map_to_curve::map_to_curve}; -use super::{ sha256::Sha256Chip, Secp256k1Chip }; +use super::{sha256::Sha256Chip, Secp256k1Chip}; pub mod constants; pub mod expand_message_xmd; @@ -18,16 +18,6 @@ pub fn hash_to_curve( secp256k1_chip: Secp256k1Chip<'_, F>, sha256_chip: &Sha256Chip, msg_bytes: &[AssignedValue], - q0_gx1_sqrt: ProperCrtUint, - q0_gx2_sqrt: ProperCrtUint, - q0_y_pos: ProperCrtUint, - q0_x_mapped: ProperCrtUint, - q0_y_mapped: ProperCrtUint, - q1_gx1_sqrt: ProperCrtUint, - q1_gx2_sqrt: ProperCrtUint, - q1_y_pos: ProperCrtUint, - q1_x_mapped: ProperCrtUint, - q1_y_mapped: ProperCrtUint ) -> EcPoint> { let fp_chip = secp256k1_chip.field_chip(); @@ -35,32 +25,14 @@ pub fn hash_to_curve( let (u0, u1) = hash_to_field(ctx, fp_chip, sha256_chip, msg_bytes); // Step 2: Q0 = map_to_curve(u[0]) - let (q0_x, q0_y2) = map_to_curve( - ctx, - fp_chip, - u0, - q0_gx1_sqrt, - q0_gx2_sqrt, - q0_y_pos, - q0_x_mapped.clone(), - q0_y_mapped.clone() - ); + let (q0_x, q0_y) = map_to_curve(ctx, fp_chip, u0); // Step 3: Q1 = map_to_curve(u[1]) - let (q1_x, q1_y2) = map_to_curve( - ctx, - fp_chip, - u1, - q1_gx1_sqrt, - q1_gx2_sqrt, - q1_y_pos, - q1_x_mapped.clone(), - q1_y_mapped.clone() - ); + let (q1_x, q1_y) = map_to_curve(ctx, fp_chip, u1); // Step 4: return A + B - let q0 = EcPoint::>::new(q0_x_mapped, q0_y_mapped); - let q1 = EcPoint::>::new(q1_x_mapped, q1_y_mapped); + let q0 = EcPoint::>::new(q0_x, q0_y); + let q1 = EcPoint::>::new(q1_x, q1_y); let point_add = secp256k1_chip.add_unequal(ctx, q0, q1, false); @@ -69,15 +41,11 @@ pub fn hash_to_curve( #[cfg(test)] mod test { - use halo2_base::{ - halo2_proofs::halo2curves::{ grumpkin::Fq as Fr, secp256k1::Secp256k1Affine, CurveAffine }, - utils::testing::base_test, - }; + use halo2_base::{halo2_proofs::halo2curves::grumpkin::Fq as Fr, utils::testing::base_test}; use crate::{ ecc::EccChip, - fields::FieldChip, - secp256k1::{ sha256::Sha256Chip, FpChip, FqChip }, + secp256k1::{sha256::Sha256Chip, FpChip}, }; use super::hash_to_curve; @@ -85,83 +53,20 @@ mod test { #[test] fn test_hash_to_curve() { let msg = b"abcdef0123456789"; - let q0_gx1_sqrt = ::ScalarExt::from([ - 8436907082510902807u64, 16481306271273964905u64, 12340693169241754123u64, 5840290864233247061u64, - ]); - let q0_gx2_sqrt = ::ScalarExt::from([ - 1u64, 0u64, 0u64, 0u64, - ]); - let q0_y_pos = ::ScalarExt::from([ - 8436907082510902807u64, 16481306271273964905u64, 12340693169241754123u64, 5840290864233247061u64, - ]); - let q0_x_mapped = ::ScalarExt::from([ - 1666473185380682589u64, 5940335290811295862u64, 16073821616946219607u64, 6299765855519516506u64, - ]); - let q0_y_mapped = ::ScalarExt::from([ - 14183132322842682307u64, 3799824159173722014u64, 17680812620347148404u64, 7222729814779291343u64, - ]); - let q1_gx1_sqrt = ::ScalarExt::from([ - 909194377947652581u64, 9506023292142230081u64, 13109065517192500057u64, 2140988711709947970u64, - ]); - let q1_gx2_sqrt = ::ScalarExt::from([ - 1u64, 0u64, 0u64, 0u64, - ]); - let q1_y_pos = ::ScalarExt::from([ - 909194377947652581u64, 9506023292142230081u64, 13109065517192500057u64, 2140988711709947970u64, - ]); - let q1_x_mapped = ::ScalarExt::from([ - 15496950058064191480u64, 16608196343028055450u64, 6698082460314400323u64, 17914594903168254206u64, - ]); - let q1_y_mapped = ::ScalarExt::from([ - 17158098838744772439u64, 14635829310764858396u64, 7975190798015443370u64, 12914166355471935767u64, - ]); - - base_test() - .k(15) - .lookup_bits(14) - .expect_satisfied(true) - .run(|ctx, range| { - let fp_chip = FpChip::::new(range, 64, 4); - let fq_chip = FqChip::::new(range, 64, 4); - let ecc_chip = EccChip::>::new(&fp_chip); - - let sha256_chip = Sha256Chip::new(range); - - let msg_bytes = msg - .iter() - .map(|&x| ctx.load_witness(Fr::from(x as u64))) - .collect::>(); - - let q0_gx1_sqrt = fq_chip.load_private(ctx, q0_gx1_sqrt); - let q0_gx2_sqrt = fq_chip.load_private(ctx, q0_gx2_sqrt); - let q0_y_pos = fq_chip.load_private(ctx, q0_y_pos); - let q0_x_mapped = fq_chip.load_private(ctx, q0_x_mapped); - let q0_y_mapped = fq_chip.load_private(ctx, q0_y_mapped); - let q1_gx1_sqrt = fq_chip.load_private(ctx, q1_gx1_sqrt); - let q1_gx2_sqrt = fq_chip.load_private(ctx, q1_gx2_sqrt); - let q1_y_pos = fq_chip.load_private(ctx, q1_y_pos); - let q1_x_mapped = fq_chip.load_private(ctx, q1_x_mapped); - let q1_y_mapped = fq_chip.load_private(ctx, q1_y_mapped); - - let point = hash_to_curve( - ctx, - ecc_chip, - &sha256_chip, - msg_bytes.as_slice(), - q0_gx1_sqrt, - q0_gx2_sqrt, - q0_y_pos, - q0_x_mapped, - q0_y_mapped, - q1_gx1_sqrt, - q1_gx2_sqrt, - q1_y_pos, - q1_x_mapped, - q1_y_mapped - ); - - println!("point x: {:?}", point.x); - println!("point y: {:?}", point.y); - }) + + base_test().k(15).lookup_bits(14).expect_satisfied(true).run(|ctx, range| { + let fp_chip = FpChip::::new(range, 64, 4); + let ecc_chip = EccChip::>::new(&fp_chip); + + let sha256_chip = Sha256Chip::new(range); + + let msg_bytes = + msg.iter().map(|&x| ctx.load_witness(Fr::from(x as u64))).collect::>(); + + let point = hash_to_curve(ctx, ecc_chip, &sha256_chip, msg_bytes.as_slice()); + + println!("point x: {:?}", point.x); + println!("point y: {:?}", point.y); + }) } } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index 66ac239d..76f25c2e 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -1,32 +1,32 @@ use halo2_base::{ - gates::{ GateInstructions, RangeChip, RangeInstructions }, - utils::{ fe_to_biguint, BigPrimeField }, - AssignedValue, - Context, - QuantumCell, + gates::{GateInstructions, RangeChip, RangeInstructions}, + utils::{fe_to_biguint, BigPrimeField}, + AssignedValue, Context, QuantumCell, }; use itertools::Itertools; -use num_bigint::{ BigUint, ToBigInt }; +use num_bigint::{BigUint, ToBigInt}; use crate::{ - bigint::{ CRTInteger, OverflowInteger, ProperCrtUint }, + bigint::{CRTInteger, OverflowInteger, ProperCrtUint}, fields::FieldChip, - secp256k1::{ util::{ bits_le_to_fe_assigned, fe_to_bits_le }, FpChip }, + secp256k1::{ + util::{bits_le_to_fe_assigned, fe_to_bits_le}, + FpChip, + }, }; // Assumes that input is a byte pub(crate) fn byte_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, - byte: &AssignedValue + byte: &AssignedValue, ) -> Vec> { let bits = fe_to_bits_le(byte.value(), 8); - let assigned_bits = bits - .iter() - .map(|bit| ctx.load_constant(F::from(*bit as u64))) - .collect_vec(); + let assigned_bits = + bits.iter().map(|bit| ctx.load_constant(F::from(*bit as u64))).collect_vec(); let _byte = bits_le_to_fe_assigned(ctx, range, &assigned_bits).unwrap(); + assert_eq!(byte.value(), _byte.value()); ctx.constrain_equal(byte, &_byte); assigned_bits @@ -35,18 +35,15 @@ pub(crate) fn byte_to_bits_le_assigned( pub(crate) fn bytes_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, - bytes: &[AssignedValue] + bytes: &[AssignedValue], ) -> Vec> { - bytes - .iter() - .flat_map(|byte| byte_to_bits_le_assigned(ctx, range, byte)) - .collect_vec() + bytes.iter().flat_map(|byte| byte_to_bits_le_assigned(ctx, range, byte)).collect_vec() } pub(crate) fn bits_le_to_byte_assigned( ctx: &mut Context, range: &RangeChip, - bits: &[AssignedValue] + bits: &[AssignedValue], ) -> AssignedValue { assert_eq!(bits.len(), 8); let gate = range.gate(); @@ -60,17 +57,15 @@ pub(crate) fn bits_le_to_byte_assigned( pub(crate) fn bits_le_to_bytes_assigned( ctx: &mut Context, range: &RangeChip, - bits: &[AssignedValue] + bits: &[AssignedValue], ) -> Vec> { - bits.chunks(8) - .map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)) - .collect_vec() + bits.chunks(8).map(|chunk| bits_le_to_byte_assigned(ctx, range, chunk)).collect_vec() } pub(crate) fn limbs_le_to_bn( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - limbs: &[AssignedValue] + limbs: &[AssignedValue], ) -> ProperCrtUint { let mut value = BigUint::from(0u64); for i in 0..limbs.len() { @@ -82,7 +77,7 @@ pub(crate) fn limbs_le_to_bn( ctx, fp_chip.range().gate(), limbs.to_vec(), - &fp_chip.limb_bases + &fp_chip.limb_bases, ); let assigned_uint = CRTInteger::new(assigned_uint, assigned_native, value.to_bigint().unwrap()); diff --git a/halo2-ecc/src/secp256k1/sha256/mod.rs b/halo2-ecc/src/secp256k1/sha256/mod.rs index 749596bd..173599d2 100644 --- a/halo2-ecc/src/secp256k1/sha256/mod.rs +++ b/halo2-ecc/src/secp256k1/sha256/mod.rs @@ -1,14 +1,12 @@ use halo2_base::{ - gates::{ GateInstructions, RangeChip, RangeInstructions }, + gates::{GateInstructions, RangeChip, RangeInstructions}, halo2_proofs::plonk::Error, utils::BigPrimeField, - AssignedValue, - Context, - QuantumCell, + AssignedValue, Context, QuantumCell, }; use itertools::Itertools; -use self::compression::{ sha256_compression, INIT_STATE }; +use self::compression::{sha256_compression, INIT_STATE}; use self::spread::SpreadChip; @@ -35,7 +33,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { &self, ctx: &mut Context, input: impl IntoIterator>, - max_len: usize + max_len: usize, ) -> Result>, Error> { let max_processed_bytes = { let mut max_bytes = max_len + 9; @@ -48,13 +46,11 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { let mut assigned_input_bytes = input .into_iter() - .map(|cell| { - match cell { - QuantumCell::Existing(v) => v, - QuantumCell::Witness(v) => ctx.load_witness(v), - QuantumCell::Constant(v) => ctx.load_constant(v), - _ => unreachable!(), - } + .map(|cell| match cell { + QuantumCell::Existing(v) => v, + QuantumCell::Witness(v) => ctx.load_witness(v), + QuantumCell::Constant(v) => ctx.load_constant(v), + _ => unreachable!(), }) .collect_vec(); @@ -97,12 +93,10 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { // compute an initial state from the precomputed_input. let last_state = INIT_STATE; - let mut assigned_last_state_vec = vec![ - last_state - .iter() - .map(|state| ctx.load_witness(F::from(*state as u64))) - .collect_vec() - ]; + let mut assigned_last_state_vec = vec![last_state + .iter() + .map(|state| ctx.load_witness(F::from(*state as u64))) + .collect_vec()]; let mut num_processed_input = 0; while num_processed_input < max_processed_bytes { @@ -112,7 +106,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { ctx, &self.spread, assigned_input_word_at_round, - assigned_last_state_vec.last().unwrap() + assigned_last_state_vec.last().unwrap(), )?; assigned_last_state_vec.push(new_assigned_hs_out); @@ -125,7 +119,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { let selector = gate.is_equal( ctx, QuantumCell::Constant(F::from(n_round as u64)), - assigned_num_round + assigned_num_round, ); for i in 0..8 { output_h_out[i] = gate.select(ctx, assigned_state[i], output_h_out[i], selector); @@ -148,7 +142,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { ctx, assigned_byte, QuantumCell::Constant(F::from(1u64 << (24 - 8 * idx))), - sum + sum, ); } ctx.constrain_equal(&assigned_word, &sum); @@ -162,7 +156,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { pub fn digest( &self, ctx: &mut Context, - input: impl IntoIterator> + input: impl IntoIterator>, ) -> Result>, Error> { let input = input.into_iter().collect_vec(); let input_len = input.len(); @@ -172,22 +166,22 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { pub fn digest_le( &self, ctx: &mut Context, - input: impl IntoIterator> + input: impl IntoIterator>, ) -> Result>, Error> { - self.digest(ctx, input) + let mut digest = self.digest(ctx, input).unwrap(); + digest.reverse(); + Ok(digest) } } #[cfg(test)] mod test { use halo2_base::{ - gates::RangeInstructions, - halo2_proofs::halo2curves::grumpkin::Fq as Fr, - utils::testing::base_test, - QuantumCell, + gates::RangeInstructions, halo2_proofs::halo2curves::grumpkin::Fq as Fr, + utils::testing::base_test, QuantumCell, }; use itertools::Itertools; - use sha2::{ Digest, Sha256 }; + use sha2::{Digest, Sha256}; use super::Sha256Chip; @@ -199,31 +193,27 @@ mod test { hasher.update(preimage); let result = hasher.finalize(); - base_test() - .k(14) - .lookup_bits(13) - .expect_satisfied(true) - .run(|ctx, range| { - let preimage_assigned = preimage - .iter() - .map(|byte| QuantumCell::Existing(ctx.load_witness(Fr::from(*byte as u64)))) - .collect_vec(); - - let result_assinged = result - .iter() - .map(|byte| { - let assigned = ctx.load_witness(Fr::from(*byte as u64)); - range.range_check(ctx, assigned, 8); - assigned - }) - .collect_vec(); - - let sha256_chip = Sha256Chip::new(range); - let digest = sha256_chip.digest(ctx, preimage_assigned).unwrap(); + base_test().k(14).lookup_bits(13).expect_satisfied(true).run(|ctx, range| { + let preimage_assigned = preimage + .iter() + .map(|byte| QuantumCell::Existing(ctx.load_witness(Fr::from(*byte as u64)))) + .collect_vec(); - for (assigned, expected) in digest.iter().zip(result_assinged.iter()) { - ctx.constrain_equal(assigned, expected); - } - }) + let result_assinged = result + .iter() + .map(|byte| { + let assigned = ctx.load_witness(Fr::from(*byte as u64)); + range.range_check(ctx, assigned, 8); + assigned + }) + .collect_vec(); + + let sha256_chip = Sha256Chip::new(range); + let digest = sha256_chip.digest(ctx, preimage_assigned).unwrap(); + + for (assigned, expected) in digest.iter().zip(result_assinged.iter()) { + ctx.constrain_equal(assigned, expected); + } + }) } } From a202c6dc792b4d601bf826e12e161c3598d3a19c Mon Sep 17 00:00:00 2001 From: shryasss Date: Wed, 14 Feb 2024 16:52:20 +0530 Subject: [PATCH 10/24] fix: minor changes --- .../hash_to_curve/expand_message_xmd.rs | 4 +- .../src/secp256k1/hash_to_curve/iso_map.rs | 44 ++++++------ .../secp256k1/hash_to_curve/map_to_curve.rs | 72 ++++++++++--------- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 10 +-- 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index 57a7e7f1..2cb2bf44 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -81,10 +81,10 @@ fn hash_b( ctx: &mut Context, sha256_chip: &Sha256Chip<'_, F>, b_idx_byte: &AssignedValue, - b_bytes: &Vec>, + b_bytes: &[AssignedValue], ) -> Vec> { assert_eq!(b_bytes.len(), 32); - assert_eq!(b_idx_byte.value() < &F::from(8u64), true); + assert!(b_idx_byte.value() < &F::from(8u64)); let dst_prime = get_dst_prime(ctx); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs index 405abacc..7a161d77 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/iso_map.rs @@ -8,9 +8,9 @@ use halo2_base::{utils::BigPrimeField, Context}; fn x_num( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - x: ProperCrtUint, - x_2: ProperCrtUint, - x_3: ProperCrtUint, + x: &ProperCrtUint, + x_2: &ProperCrtUint, + x_3: &ProperCrtUint, ) -> ProperCrtUint { let k_1_3 = get_k_1_3(ctx, fp_chip); let k_1_2 = get_k_1_2(ctx, fp_chip); @@ -44,8 +44,8 @@ fn x_num( fn x_den( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - x: ProperCrtUint, - x_2: ProperCrtUint, + x: &ProperCrtUint, + x_2: &ProperCrtUint, ) -> ProperCrtUint { let k_2_0 = get_k_2_0(ctx, fp_chip); let k_2_1 = get_k_2_1(ctx, fp_chip); @@ -67,9 +67,9 @@ fn x_den( fn y_num( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - x: ProperCrtUint, - x_2: ProperCrtUint, - x_3: ProperCrtUint, + x: &ProperCrtUint, + x_2: &ProperCrtUint, + x_3: &ProperCrtUint, ) -> ProperCrtUint { let k_3_3 = get_k_3_3(ctx, fp_chip); let k_3_2 = get_k_3_2(ctx, fp_chip); @@ -103,9 +103,9 @@ fn y_num( fn y_den( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - x: ProperCrtUint, - x_2: ProperCrtUint, - x_3: ProperCrtUint, + x: &ProperCrtUint, + x_2: &ProperCrtUint, + x_3: &ProperCrtUint, ) -> ProperCrtUint { let k_4_0 = get_k_4_0(ctx, fp_chip); let k_4_1 = get_k_4_1(ctx, fp_chip); @@ -135,30 +135,30 @@ fn y_den( pub(crate) fn iso_map( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - x: ProperCrtUint, - y: ProperCrtUint, + x: &ProperCrtUint, + y: &ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { // Step 1: calculate x^2 - let x_2 = fp_chip.mul(ctx, x.clone(), x.clone()); + let x_2 = fp_chip.mul(ctx, x, x); // Step 2: calculate x^3 - let x_3 = fp_chip.mul(ctx, x.clone(), x_2.clone()); + let x_3 = fp_chip.mul(ctx, x, &x_2); // Step 3: calculate x_num - let x_num = x_num(ctx, fp_chip, x.clone(), x_2.clone(), x_3.clone()); + let x_num = x_num(ctx, fp_chip, x, &x_2, &x_3); // Step 4: calculate x_den - let x_den = x_den(ctx, fp_chip, x.clone(), x_2.clone()); + let x_den = x_den(ctx, fp_chip, x, &x_2); // Step 5: calculate y_num - let y_num = y_num(ctx, fp_chip, x.clone(), x_2.clone(), x_3.clone()); + let y_num = y_num(ctx, fp_chip, x, &x_2, &x_3); // Step 6: calculate y_den - let y_den = y_den(ctx, fp_chip, x, x_2, x_3); + let y_den = y_den(ctx, fp_chip, x, &x_2, &x_3); - let x_mapped = fp_chip.divide(ctx, x_num.clone(), x_den.clone()); - let y_mapped = fp_chip.divide(ctx, y_num.clone(), y_den.clone()); - let y_mapped = fp_chip.mul(ctx, y_mapped, y.clone()); + let x_mapped = fp_chip.divide(ctx, &x_num, &x_den); + let y_mapped = fp_chip.divide(ctx, &y_num, &y_den); + let y_mapped = fp_chip.mul(ctx, &y_mapped, y); (x_mapped, y_mapped) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 9e03c47b..66566af1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -21,29 +21,29 @@ use crate::{ fn xy2_selector( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - gx1: ProperCrtUint, - gx2: ProperCrtUint, - x1: ProperCrtUint, - x2: ProperCrtUint, + gx1: &ProperCrtUint, + gx2: &ProperCrtUint, + x1: &ProperCrtUint, + x2: &ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { let gate = fp_chip.range().gate(); let one = ctx.load_constant(F::ONE); - let gx1_sqrt = sqrt(ctx, fp_chip, gx1.clone()); - let gx2_sqrt = sqrt(ctx, fp_chip, gx2.clone()); + let gx1_sqrt = sqrt(ctx, fp_chip, gx1); + let gx2_sqrt = sqrt(ctx, fp_chip, gx2); - let sq_gx1_sqrt = fp_chip.mul(ctx, gx1_sqrt.clone(), gx1_sqrt); - let sq_gx2_sqrt = fp_chip.mul(ctx, gx2_sqrt.clone(), gx2_sqrt); + let sq_gx1_sqrt = fp_chip.mul(ctx, &gx1_sqrt, &gx1_sqrt); + let sq_gx2_sqrt = fp_chip.mul(ctx, &gx2_sqrt, &gx2_sqrt); - let s1 = fp_chip.is_equal(ctx, sq_gx1_sqrt.clone(), gx1.clone()); - let s2 = fp_chip.is_equal(ctx, sq_gx2_sqrt.clone(), gx2.clone()); + let s1 = fp_chip.is_equal(ctx, &sq_gx1_sqrt, gx1); + let s2 = fp_chip.is_equal(ctx, &sq_gx2_sqrt, gx2); let _one = gate.add(ctx, s1, s2); assert_eq!(_one.value(), &F::ONE); ctx.constrain_equal(&_one, &one); - let x = fp_chip.select(ctx, x1, x2, s1); - let y2 = fp_chip.select(ctx, gx1, gx2, s1); + let x = fp_chip.select(ctx, x1.into(), x2.into(), s1); + let y2 = fp_chip.select(ctx, gx1.into(), gx2.into(), s1); (x, y2) } @@ -51,7 +51,7 @@ fn xy2_selector( fn mod_inverse( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - num: ProperCrtUint, + num: &ProperCrtUint, ) -> ProperCrtUint { let one = ctx.load_constant(F::ONE); let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); @@ -64,7 +64,7 @@ fn mod_inverse( assert_eq!((num_native * inverse_native.clone()) % p, BigUint::from(1u64)); let mod_inverse = fp_chip.load_constant_uint(ctx, inverse_native); - let is_one = fp_chip.mul(ctx, num, mod_inverse.clone()); + let is_one = fp_chip.mul(ctx, num, &mod_inverse); let is_equal = fp_chip.is_equal(ctx, is_one, one_int); assert_eq!(is_equal.value(), &F::ONE); ctx.constrain_equal(&is_equal, &one); @@ -75,7 +75,7 @@ fn mod_inverse( pub(crate) fn sqrt( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - num: ProperCrtUint, + num: &ProperCrtUint, ) -> ProperCrtUint { let p = fp_chip.p.to_biguint().unwrap(); let p_plus_1 = p.clone() + 1u64; @@ -90,36 +90,38 @@ pub(crate) fn sqrt( pub(crate) fn map_to_curve( ctx: &mut Context, fp_chip: &FpChip<'_, F>, - u: ProperCrtUint, + u: &ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { let range = fp_chip.range(); let gate = range.gate(); let one = ctx.load_constant(F::ONE); - let zero_int = fp_chip.load_constant_uint(ctx, BigUint::from(0u64)); - let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); + let zero_int = + fp_chip.load_constant(ctx, Fp::from_bytes_le(BigUint::from(0u64).to_bytes_le().as_slice())); + let one_int = + fp_chip.load_constant(ctx, Fp::from_bytes_le(BigUint::from(1u64).to_bytes_le().as_slice())); // Step 1: tv1 = Z * u^2 - let u_sq = fp_chip.mul(ctx, u.clone(), u.clone()); + let u_sq = fp_chip.mul(ctx, u, u); let z = get_Z(ctx, fp_chip); let tv1 = fp_chip.mul(ctx, z, u_sq); // Step 2: tv2 = tv1^2 - let tv2 = fp_chip.mul(ctx, tv1.clone(), tv1.clone()); + let tv2 = fp_chip.mul(ctx, &tv1, &tv1); // Step 3: x1 = tv1 + tv2 - let x1 = fp_chip.add_no_carry(ctx, tv1.clone(), tv2.clone()); + let x1 = fp_chip.add_no_carry(ctx, &tv1, &tv2); let x1 = fp_chip.carry_mod(ctx, x1); // Step 4: x1 = inv0(x1) - let x1 = mod_inverse(ctx, fp_chip, x1); + let x1 = mod_inverse(ctx, fp_chip, &x1); - // Step 5: e1 = x1 == 0 - let e1 = fp_chip.is_equal(ctx, x1.clone(), zero_int); + // Step 5: e1 = x1 == 0& + let e1 = fp_chip.is_equal(ctx, &x1, zero_int); // Step 6: x1 = x1 + 1 - let x1 = fp_chip.add_no_carry(ctx, x1.clone(), one_int); + let x1 = fp_chip.add_no_carry(ctx, &x1, one_int); let x1 = fp_chip.carry_mod(ctx, x1); // Step 7: x1 = e1 ? c2 : x1 @@ -128,10 +130,10 @@ pub(crate) fn map_to_curve( // Step 8: x1 = x1 * c1 # x1 = (-B / A) * (1 + (1 / (Z^2 * u^4 + Z * u^2))) let c1 = get_C1(ctx, fp_chip); - let x1 = fp_chip.mul(ctx, x1.clone(), c1); + let x1 = fp_chip.mul(ctx, &x1, c1); // Step 9: gx1 = x1^2 - let gx1 = fp_chip.mul(ctx, x1.clone(), x1.clone()); + let gx1 = fp_chip.mul(ctx, &x1, &x1); // Step 10: gx1 = gx1 + A let a = get_A(ctx, fp_chip); @@ -139,7 +141,7 @@ pub(crate) fn map_to_curve( let gx1 = fp_chip.carry_mod(ctx, gx1); // Step 11: gx1 = gx1 * x1 - let gx1 = fp_chip.mul(ctx, gx1, x1.clone()); + let gx1 = fp_chip.mul(ctx, gx1, &x1); // Step 12: gx1 = gx1 + B # gx1 = g(x1) = x1^3 + A * x1 + B let b = get_B(ctx, fp_chip); @@ -147,37 +149,37 @@ pub(crate) fn map_to_curve( let gx1 = fp_chip.carry_mod(ctx, gx1); // Step 13: x2 = tv1 * x1 # x2 = Z * u^2 * x1 - let x2 = fp_chip.mul(ctx, tv1.clone(), x1.clone()); + let x2 = fp_chip.mul(ctx, &tv1, &x1); // Step 14: tv2 = tv1 * tv2 let tv2 = fp_chip.mul(ctx, tv1, tv2); // Step 15: gx2 = gx1 * tv2 # gx2 = (Z * u^2)^3 * gx1 - let gx2 = fp_chip.mul(ctx, gx1.clone(), tv2); + let gx2 = fp_chip.mul(ctx, &gx1, tv2); // Steps 16-18: // e2 = is_square(gx1) // x = CMOV(x2, x1, e2) # If is_square(gx1), x = x1, else x = x2 // y2 = CMOV(gx2, gx1, e2) # If is_square(gx1), y2 = gx1, else y2 = gx2 - let (x, y2) = xy2_selector(ctx, fp_chip, gx1, gx2, x1, x2); + let (x, y2) = xy2_selector(ctx, fp_chip, &gx1, &gx2, &x1, &x2); // Step 19: y = sqrt(y2) - let y = sqrt(ctx, fp_chip, y2.clone()); - let y_sq = fp_chip.mul(ctx, y.clone(), y.clone()); + let y = sqrt(ctx, fp_chip, &y2); + let y_sq = fp_chip.mul(ctx, &y, &y); let e2 = fp_chip.is_equal(ctx, y_sq, y2); assert_eq!(e2.value(), &F::ONE); ctx.constrain_equal(&e2, &one); // Step 20: e3 = sgn0(u) == sgn0(y) # Fix sign of y let sgn_u = fp_chip.is_even(ctx, u); - let sgn_y = fp_chip.is_even(ctx, y.clone()); + let sgn_y = fp_chip.is_even(ctx, &y); let e3 = gate.is_equal(ctx, sgn_u, sgn_y); // Step 21: y = e3 ? y : -y let neg_y = fp_chip.negate(ctx, y.clone()); let y = fp_chip.select(ctx, y, neg_y, e3); - let (x_mapped, y_mapped) = iso_map(ctx, fp_chip, x.clone(), y.clone()); + let (x_mapped, y_mapped) = iso_map(ctx, fp_chip, &x, &y); (x_mapped, y_mapped) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index 04badc86..b58302b9 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -25,10 +25,10 @@ pub fn hash_to_curve( let (u0, u1) = hash_to_field(ctx, fp_chip, sha256_chip, msg_bytes); // Step 2: Q0 = map_to_curve(u[0]) - let (q0_x, q0_y) = map_to_curve(ctx, fp_chip, u0); + let (q0_x, q0_y) = map_to_curve(ctx, fp_chip, &u0); // Step 3: Q1 = map_to_curve(u[1]) - let (q1_x, q1_y) = map_to_curve(ctx, fp_chip, u1); + let (q1_x, q1_y) = map_to_curve(ctx, fp_chip, &u1); // Step 4: return A + B let q0 = EcPoint::>::new(q0_x, q0_y); @@ -52,7 +52,7 @@ mod test { #[test] fn test_hash_to_curve() { - let msg = b"abcdef0123456789"; + let msg = b"abc"; base_test().k(15).lookup_bits(14).expect_satisfied(true).run(|ctx, range| { let fp_chip = FpChip::::new(range, 64, 4); @@ -65,8 +65,8 @@ mod test { let point = hash_to_curve(ctx, ecc_chip, &sha256_chip, msg_bytes.as_slice()); - println!("point x: {:?}", point.x); - println!("point y: {:?}", point.y); + println!("point x: {:?}", point.x.value().to_str_radix(16)); + println!("point y: {:?}", point.y.value().to_str_radix(16)); }) } } From 90d647b954dfa96e91b12e973549084999aae19c Mon Sep 17 00:00:00 2001 From: shryasss Date: Wed, 14 Feb 2024 18:58:49 +0530 Subject: [PATCH 11/24] =?UTF-8?q?feat:=20hash=5Fto=5Fcurve=20working=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/secp256k1/hash_to_curve/constants.rs | 249 ++++++++++-------- .../secp256k1/hash_to_curve/hash_to_field.rs | 38 ++- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 8 +- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 5 +- 4 files changed, 166 insertions(+), 134 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs index 8349de11..53e623e5 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/constants.rs @@ -1,6 +1,7 @@ -use super::util::limbs_le_to_bn; use crate::{bigint::ProperCrtUint, secp256k1::FpChip}; use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; +use num_bigint::BigUint; +use num_traits::Num; pub(crate) fn get_z_pad(ctx: &mut Context) -> Vec> { let zero = ctx.load_zero(); @@ -27,13 +28,14 @@ pub(crate) fn get_Z( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let z = - [18446744069414583332, 18446744073709551615, 18446744073709551615, 18446744073709551615] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, z.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "115792089237316195423570985008687907853269984665640564039457584007908834671652", + 10, + ) + .unwrap(), + ) } // A = 28734576633528757162648956269730739219262246272443394170905244663053633733939 @@ -41,45 +43,51 @@ pub(crate) fn get_A( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let a = [4635408806871057715, 16813014259472469597, 11568152433342665330, 4577682160469023452] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, a.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "28734576633528757162648956269730739219262246272443394170905244663053633733939", + 10, + ) + .unwrap(), + ) } pub(crate) fn get_B( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let b = [1771, 0, 0, 0].iter().map(|v| ctx.load_constant(F::from(*v))).collect::>(); - - limbs_le_to_bn(ctx, fp_chip, b.as_slice()) + fp_chip.load_constant_uint(ctx, BigUint::from(1771u64)) } +// c1 = 5324262023205125242632636178842408935272934169651804884418803605709653231043 pub(crate) fn get_C1( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let c1 = [12250307269654431171, 7923238676646950141, 11532678464006552332, 848203876191778994] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, c1.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "5324262023205125242632636178842408935272934169651804884418803605709653231043", + 10, + ) + .unwrap(), + ) } +// c2 = 31579660701086235115519359547823974869073632181538335647124795638520591274090 pub(crate) fn get_C2( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let c2 = [1676976732802240618, 15092790605762360413, 6707906935894382405, 5030930201920786804] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, c2.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "31579660701086235115519359547823974869073632181538335647124795638520591274090", + 10, + ) + .unwrap(), + ) } // k_(1,0) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7 @@ -87,12 +95,14 @@ pub(crate) fn get_k_1_0( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [10248191149674768583, 4099276460824344803, 16397105843297379214, 10248191152060862008] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7", + 16, + ) + .unwrap(), + ) } // k_(1,1) = 0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581 @@ -100,12 +110,14 @@ pub(crate) fn get_k_1_1( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [16140637477814429057, 15390439281582816146, 13399077293683197125, 564028334007329237] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581", + 16, + ) + .unwrap(), + ) } // k_(1,2) = 0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262 @@ -113,12 +125,14 @@ pub(crate) fn get_k_1_2( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [5677861232072053346, 16451756383528566833, 16331199996347402988, 6002227985152881894] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262", + 16, + ) + .unwrap(), + ) } // k_(1,3) = 0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c @@ -126,12 +140,14 @@ pub(crate) fn get_k_1_3( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [10248191149674768524, 4099276460824344803, 16397105843297379214, 10248191152060862008] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c", + 16, + ) + .unwrap(), + ) } // k_(2,0) = 0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b @@ -139,12 +155,14 @@ pub(crate) fn get_k_2_0( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [11522098205669897371, 9713490981125900413, 11286949528964841693, 15228765018197889418] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "d35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b", + 16, + ) + .unwrap(), + ) } // k_(2,1) = 0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14 @@ -152,12 +170,14 @@ pub(crate) fn get_k_2_1( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [14207262949819313428, 491854862080688571, 17853591451159765588, 17126563718956833821] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "edadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14", + 16, + ) + .unwrap(), + ) } // k_(3,0) = 0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c @@ -165,12 +185,14 @@ pub(crate) fn get_k_3_0( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [11614616637729727036, 3416063717353620669, 7515340178177965473, 5465701947765793071] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c", + 16, + ) + .unwrap(), + ) } // k_(3,1) = 0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3 @@ -178,12 +200,14 @@ pub(crate) fn get_k_3_1( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [16139934577133973923, 7240293169244854895, 12236461929419286229, 14365933273833241615] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "c75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3", + 16, + ) + .unwrap(), + ) } // k_(3,2) = 0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931 @@ -191,12 +215,14 @@ pub(crate) fn get_k_3_2( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [12062302652890802481, 8225878191764283416, 8165599998173701494, 3001113992576440947] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931", + 16, + ) + .unwrap(), + ) } // k_(3,3) = 0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84 @@ -204,12 +230,14 @@ pub(crate) fn get_k_3_3( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [9564978407794773380, 13664254869414482678, 11614616639002310276, 3416063717353620669] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84", + 16, + ) + .unwrap(), + ) } // k_(4,0) = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b @@ -217,13 +245,14 @@ pub(crate) fn get_k_4_0( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = - [18446744069414582587, 18446744073709551615, 18446744073709551615, 18446744073709551615] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b", + 16, + ) + .unwrap(), + ) } // k_(4,1) = 0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573 @@ -231,12 +260,14 @@ pub(crate) fn get_k_4_1( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [16119550551890077043, 10693728869668149624, 15414104513184973464, 8792806907174565023] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573", + 16, + ) + .unwrap(), + ) } // k_(4,2) = 0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f @@ -244,10 +275,12 @@ pub(crate) fn get_k_4_2( ctx: &mut Context, fp_chip: &FpChip<'_, F>, ) -> ProperCrtUint { - let k = [12087522392169162607, 737782293121032857, 17557015139884872574, 7243101504725699116] - .iter() - .map(|v| ctx.load_constant(F::from(*v))) - .collect::>(); - - limbs_le_to_bn(ctx, fp_chip, k.as_slice()) + fp_chip.load_constant_uint( + ctx, + BigUint::from_str_radix( + "6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f", + 16, + ) + .unwrap(), + ) } diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs index 16d097ce..2ae6c4d0 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/hash_to_field.rs @@ -9,30 +9,23 @@ use halo2_base::{ utils::BigPrimeField, AssignedValue, Context, QuantumCell, }; +use itertools::Itertools; use num_bigint::BigUint; -use num_integer::div_ceil; fn bytes_le_to_limbs( ctx: &mut Context, fp_chip: &FpChip<'_, F>, bytes: &[AssignedValue], ) -> Vec> { - let mut limbs = Vec::>::with_capacity(div_ceil(bytes.len(), 8)); - for chunk in bytes.chunks(8) { - let mut limb = ctx.load_zero(); - for i in 0..8 { - if chunk.len() < 8 && i >= chunk.len() { - break; - } - limb = fp_chip.range().gate().mul_add( - ctx, - chunk[i], - QuantumCell::Constant(F::from(1 << (8 * i))), - limb, - ); - } - limbs.push(limb); - } + let gate = fp_chip.range().gate(); + + let limb_bytes = fp_chip.limb_bits() / 8; + let byte_base = + (0..limb_bytes).map(|i| QuantumCell::Constant(gate.pow_of_two()[i * 8])).collect_vec(); + let limbs = bytes + .chunks(limb_bytes) + .map(|chunk| gate.inner_product(ctx, chunk.to_vec(), byte_base[..chunk.len()].to_vec())) + .collect::>(); limbs } @@ -44,18 +37,17 @@ fn bytes_to_registers( ) -> ProperCrtUint { let limbs = bytes_le_to_limbs(ctx, fp_chip, bytes); - let mut lo_limbs = limbs[..3].to_vec(); - lo_limbs.push(ctx.load_zero()); + let lo_limbs = limbs[..3].to_vec(); let mut hi_limbs = limbs[3..].to_vec(); hi_limbs.push(ctx.load_zero()); - let lo = limbs_le_to_bn(ctx, fp_chip, lo_limbs.as_slice()); - let hi = limbs_le_to_bn(ctx, fp_chip, hi_limbs.as_slice()); + let lo = limbs_le_to_bn(ctx, fp_chip, lo_limbs.as_slice(), fp_chip.limb_bits()); + let hi = limbs_le_to_bn(ctx, fp_chip, hi_limbs.as_slice(), fp_chip.limb_bits()); - let two_power_192 = fp_chip.load_constant_uint(ctx, BigUint::from(2u8).pow(192)); + let two_power_264 = fp_chip.load_constant_uint(ctx, BigUint::from(2u8).pow(264)); - let num = fp_chip.mul_no_carry(ctx, hi, two_power_192); + let num = fp_chip.mul_no_carry(ctx, hi, two_power_264); let num = fp_chip.add_no_carry(ctx, num, lo); let num = fp_chip.carry_mod(ctx, num); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index b58302b9..7df350ec 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -23,12 +23,18 @@ pub fn hash_to_curve( // Step 1: u = hash_to_field(msg) let (u0, u1) = hash_to_field(ctx, fp_chip, sha256_chip, msg_bytes); + println!("u0: {:?}", u0.value().to_str_radix(16)); + println!("u1: {:?}", u1.value().to_str_radix(16)); // Step 2: Q0 = map_to_curve(u[0]) let (q0_x, q0_y) = map_to_curve(ctx, fp_chip, &u0); + println!("q0_x: {:?}", q0_x.value().to_str_radix(16)); + println!("q0_y: {:?}", q0_y.value().to_str_radix(16)); // Step 3: Q1 = map_to_curve(u[1]) let (q1_x, q1_y) = map_to_curve(ctx, fp_chip, &u1); + println!("q1_x: {:?}", q1_x.value().to_str_radix(16)); + println!("q1_y: {:?}", q1_y.value().to_str_radix(16)); // Step 4: return A + B let q0 = EcPoint::>::new(q0_x, q0_y); @@ -55,7 +61,7 @@ mod test { let msg = b"abc"; base_test().k(15).lookup_bits(14).expect_satisfied(true).run(|ctx, range| { - let fp_chip = FpChip::::new(range, 64, 4); + let fp_chip = FpChip::::new(range, 88, 3); let ecc_chip = EccChip::>::new(&fp_chip); let sha256_chip = Sha256Chip::new(range); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index 76f25c2e..ad8a8a82 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -66,13 +66,14 @@ pub(crate) fn limbs_le_to_bn( ctx: &mut Context, fp_chip: &FpChip<'_, F>, limbs: &[AssignedValue], + max_limb_bits: usize, ) -> ProperCrtUint { let mut value = BigUint::from(0u64); for i in 0..limbs.len() { - value += (BigUint::from(1u64) << (64 * i)) * fe_to_biguint(limbs[i].value()); + value += (BigUint::from(1u64) << (max_limb_bits * i)) * fe_to_biguint(limbs[i].value()); } - let assigned_uint = OverflowInteger::new(limbs.to_vec(), 64); + let assigned_uint = OverflowInteger::new(limbs.to_vec(), max_limb_bits); let assigned_native = OverflowInteger::evaluate_native( ctx, fp_chip.range().gate(), From 23f3419faec31424d3437bb6ab05458db90f3751 Mon Sep 17 00:00:00 2001 From: shryasss Date: Thu, 15 Feb 2024 07:56:47 +0530 Subject: [PATCH 12/24] test: added more test cases --- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 93 +++++++++++++++++--- 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index 7df350ec..cc87e2ed 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -15,7 +15,7 @@ pub mod util; pub fn hash_to_curve( ctx: &mut Context, - secp256k1_chip: Secp256k1Chip<'_, F>, + secp256k1_chip: &Secp256k1Chip<'_, F>, sha256_chip: &Sha256Chip, msg_bytes: &[AssignedValue], ) -> EcPoint> { @@ -23,18 +23,12 @@ pub fn hash_to_curve( // Step 1: u = hash_to_field(msg) let (u0, u1) = hash_to_field(ctx, fp_chip, sha256_chip, msg_bytes); - println!("u0: {:?}", u0.value().to_str_radix(16)); - println!("u1: {:?}", u1.value().to_str_radix(16)); // Step 2: Q0 = map_to_curve(u[0]) let (q0_x, q0_y) = map_to_curve(ctx, fp_chip, &u0); - println!("q0_x: {:?}", q0_x.value().to_str_radix(16)); - println!("q0_y: {:?}", q0_y.value().to_str_radix(16)); // Step 3: Q1 = map_to_curve(u[1]) let (q1_x, q1_y) = map_to_curve(ctx, fp_chip, &u1); - println!("q1_x: {:?}", q1_x.value().to_str_radix(16)); - println!("q1_y: {:?}", q1_y.value().to_str_radix(16)); // Step 4: return A + B let q0 = EcPoint::>::new(q0_x, q0_y); @@ -56,9 +50,74 @@ mod test { use super::hash_to_curve; + struct TestData { + message: String, + point: (String, String), + } + #[test] fn test_hash_to_curve() { - let msg = b"abc"; + let test_data = vec![ + TestData { + message: String::from(""), + point: ( + String::from( + "c1cae290e291aee617ebaef1be6d73861479c48b841eaba9b7b5852ddfeb1346" + ), + String::from( + "64fa678e07ae116126f08b022a94af6de15985c996c3a91b64c406a960e51067" + ), + ), + }, + TestData { + message: String::from("abc"), + point: ( + String::from( + "3377e01eab42db296b512293120c6cee72b6ecf9f9205760bd9ff11fb3cb2c4b" + ), + String::from( + "7f95890f33efebd1044d382a01b1bee0900fb6116f94688d487c6c7b9c8371f6" + ), + ), + }, + TestData { + message: String::from("abcdef0123456789"), + point: ( + String::from( + "bac54083f293f1fe08e4a70137260aa90783a5cb84d3f35848b324d0674b0e3a" + ), + String::from( + "4436476085d4c3c4508b60fcf4389c40176adce756b398bdee27bca19758d828" + ), + ), + }, + TestData { + message: String::from( + "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" + ), + point: ( + String::from( + "e2167bc785333a37aa562f021f1e881defb853839babf52a7f72b102e41890e9" + ), + String::from( + "f2401dd95cc35867ffed4f367cd564763719fbc6a53e969fb8496a1e6685d873" + ), + ), + }, + TestData { + message: String::from( + "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ), + point: ( + String::from( + "e3c8d35aaaf0b9b647e88a0a0a7ee5d5bed5ad38238152e4e6fd8c1f8cb7c998" + ), + String::from( + "8446eeb6181bf12f56a9d24e262221cc2f0c4725c7e3803024b5888ee5823aa6" + ), + ), + } + ]; base_test().k(15).lookup_bits(14).expect_satisfied(true).run(|ctx, range| { let fp_chip = FpChip::::new(range, 88, 3); @@ -66,13 +125,19 @@ mod test { let sha256_chip = Sha256Chip::new(range); - let msg_bytes = - msg.iter().map(|&x| ctx.load_witness(Fr::from(x as u64))).collect::>(); + for i in 0..test_data.len() { + let msg_bytes = test_data[i] + .message + .as_bytes() + .iter() + .map(|&x| ctx.load_witness(Fr::from(x as u64))) + .collect::>(); - let point = hash_to_curve(ctx, ecc_chip, &sha256_chip, msg_bytes.as_slice()); + let point = hash_to_curve(ctx, &ecc_chip, &sha256_chip, msg_bytes.as_slice()); - println!("point x: {:?}", point.x.value().to_str_radix(16)); - println!("point y: {:?}", point.y.value().to_str_radix(16)); - }) + assert_eq!(point.x.value().to_str_radix(16), test_data[i].point.0); + assert_eq!(point.y.value().to_str_radix(16), test_data[i].point.1); + } + }); } } From 39a84fed3035600f439230c4d0c4f4dce18b7a37 Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Mon, 22 Apr 2024 16:48:43 +0530 Subject: [PATCH 13/24] fix: added missing bit range checks --- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 12 ++++++++++-- halo2-ecc/src/secp256k1/util.rs | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index ad8a8a82..0a6d2b21 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -21,9 +21,16 @@ pub(crate) fn byte_to_bits_le_assigned( range: &RangeChip, byte: &AssignedValue, ) -> Vec> { + range.range_check(ctx, *byte, 8); let bits = fe_to_bits_le(byte.value(), 8); - let assigned_bits = - bits.iter().map(|bit| ctx.load_constant(F::from(*bit as u64))).collect_vec(); + let assigned_bits = bits + .iter() + .map(|bit| { + let bit = ctx.load_constant(F::from(*bit as u64)); + range.gate().assert_bit(ctx, bit); + bit + }) + .collect_vec(); let _byte = bits_le_to_fe_assigned(ctx, range, &assigned_bits).unwrap(); assert_eq!(byte.value(), _byte.value()); @@ -49,6 +56,7 @@ pub(crate) fn bits_le_to_byte_assigned( let gate = range.gate(); let mut sum = ctx.load_zero(); for (idx, bit) in bits.iter().enumerate() { + gate.assert_bit(ctx, *bit); sum = gate.mul_add(ctx, *bit, QuantumCell::Constant(F::from(1 << idx)), sum); } sum diff --git a/halo2-ecc/src/secp256k1/util.rs b/halo2-ecc/src/secp256k1/util.rs index 2e8e723b..b3ead1d5 100644 --- a/halo2-ecc/src/secp256k1/util.rs +++ b/halo2-ecc/src/secp256k1/util.rs @@ -39,6 +39,7 @@ pub fn bits_le_to_fe_assigned( let gate = range.gate(); let mut sum = ctx.load_zero(); for (idx, bit) in bits.iter().enumerate() { + gate.assert_bit(ctx, *bit); sum = gate.mul_add( ctx, QuantumCell::Existing(*bit), From bffb7900dc11d7fcb0bc4ce911356681ac9cdb8d Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Fri, 26 Apr 2024 10:43:23 +0530 Subject: [PATCH 14/24] fix: changed utils functions --- .../hash_to_curve/expand_message_xmd.rs | 4 ++- halo2-ecc/src/secp256k1/hash_to_curve/util.rs | 33 +++---------------- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs index 2cb2bf44..bec46975 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/expand_message_xmd.rs @@ -10,7 +10,7 @@ use halo2_base::{ }; fn calc_msg_prime_output_length(msg_length: usize) -> usize { - msg_length + 64 + 2 + 50 + 1 + msg_length + 64 + 2 + 50 + 1 // msg + z_pad + lib_str + dst_prime + 0 } fn msg_prime( @@ -51,6 +51,7 @@ fn hash_msg_prime_to_b0( msg_prime_bytes: &[AssignedValue], ) -> Vec> { let msg_prime_bytes = msg_prime_bytes.iter().map(|byte| QuantumCell::Existing(*byte)); + // TODO: Have a max len for the sha hash. let hash = sha256_chip.digest(ctx, msg_prime_bytes).unwrap(); hash } @@ -94,6 +95,7 @@ fn hash_b( preimage.extend(dst_prime); let preimage = preimage.iter().map(|byte| QuantumCell::Existing(*byte)); + // TODO: Have a max len for the sha hash. let hash = sha256_chip.digest(ctx, preimage).unwrap(); hash diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs index 0a6d2b21..f6408bb3 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/util.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/util.rs @@ -1,7 +1,7 @@ use halo2_base::{ gates::{GateInstructions, RangeChip, RangeInstructions}, utils::{fe_to_biguint, BigPrimeField}, - AssignedValue, Context, QuantumCell, + AssignedValue, Context, }; use itertools::Itertools; use num_bigint::{BigUint, ToBigInt}; @@ -9,34 +9,16 @@ use num_bigint::{BigUint, ToBigInt}; use crate::{ bigint::{CRTInteger, OverflowInteger, ProperCrtUint}, fields::FieldChip, - secp256k1::{ - util::{bits_le_to_fe_assigned, fe_to_bits_le}, - FpChip, - }, + secp256k1::FpChip, }; -// Assumes that input is a byte pub(crate) fn byte_to_bits_le_assigned( ctx: &mut Context, range: &RangeChip, byte: &AssignedValue, ) -> Vec> { range.range_check(ctx, *byte, 8); - let bits = fe_to_bits_le(byte.value(), 8); - let assigned_bits = bits - .iter() - .map(|bit| { - let bit = ctx.load_constant(F::from(*bit as u64)); - range.gate().assert_bit(ctx, bit); - bit - }) - .collect_vec(); - - let _byte = bits_le_to_fe_assigned(ctx, range, &assigned_bits).unwrap(); - assert_eq!(byte.value(), _byte.value()); - ctx.constrain_equal(byte, &_byte); - - assigned_bits + range.gate().num_to_bits(ctx, *byte, 8) } pub(crate) fn bytes_to_bits_le_assigned( @@ -53,13 +35,8 @@ pub(crate) fn bits_le_to_byte_assigned( bits: &[AssignedValue], ) -> AssignedValue { assert_eq!(bits.len(), 8); - let gate = range.gate(); - let mut sum = ctx.load_zero(); - for (idx, bit) in bits.iter().enumerate() { - gate.assert_bit(ctx, *bit); - sum = gate.mul_add(ctx, *bit, QuantumCell::Constant(F::from(1 << idx)), sum); - } - sum + let _ = bits.iter().map(|bit| range.gate().assert_bit(ctx, *bit)); + range.gate().bits_to_num(ctx, bits) } pub(crate) fn bits_le_to_bytes_assigned( From 5b64f76c88b038495cdc8104f26f295a1cf6954d Mon Sep 17 00:00:00 2001 From: Yush G Date: Sat, 9 Mar 2024 16:40:06 -0800 Subject: [PATCH 15/24] Add link to PLUME to examples (#263) Add PLUME to examples --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0dd0370e..b38eb324 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ cd halo2-lib - [halo2-rsa](https://github.com/zkemail/halo2-rsa/tree/feat/new_bigint) - [halo2-fri-gadget](https://github.com/maxgillett/halo2-fri-gadget) -- FRI verifier in halo2. - [eth-voice-recovery](https://github.com/SoraSuegami/voice_recovery_circuit) -- Verify the voice recovery process. +- [PLUME ERC 7524 Signatures](https://github.com/plume-sig/zk-nullifier-sig/pull/83) - Verify deterministic PLUME signatures of Ethereum keys, for private voting nullifiers. - [zkEVM signature verification circuit](https://github.com/scroll-tech/zkevm-circuits/tree/develop/zkevm-circuits/src/sig_circuit.rs) - [zkEVM tx-circuit](https://github.com/scroll-tech/zkevm-circuits/tree/develop/zkevm-circuits/src/tx_circuit) - [webauthn-halo2](https://github.com/zkwebauthn/webauthn-halo2) -- Proving and verifying WebAuthn with halo2. From 63d58f5682cedc14cd46f65e43aa46fdc10b6c38 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 22 Mar 2024 14:17:32 -0700 Subject: [PATCH 16/24] chore: update rust toolchain (#266) * chore: fix link (#256) * chore: update `snark-verifier` git tag in `zkevm-hashes` * chore: update rust toolchain * chore: fix clippy * chore: update should_panic message * chore: switch to community-edition --------- Co-authored-by: yanziseeker <153156292+AdventureSeeker987@users.noreply.github.com> --- halo2-base/src/gates/flex_gate/mod.rs | 2 +- halo2-base/src/poseidon/hasher/tests/mod.rs | 8 ++++---- halo2-ecc/src/secp256k1/tests/ecdsa_tests.rs | 8 ++++++-- hashes/zkevm/Cargo.toml | 4 ++-- hashes/zkevm/src/keccak/component/circuit/tests/shard.rs | 2 +- rust-toolchain | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/halo2-base/src/gates/flex_gate/mod.rs b/halo2-base/src/gates/flex_gate/mod.rs index 03f952b6..4ed3b4c3 100644 --- a/halo2-base/src/gates/flex_gate/mod.rs +++ b/halo2-base/src/gates/flex_gate/mod.rs @@ -137,7 +137,7 @@ impl FlexGateConfig { Self { basic_gates, constants, - /// Warning: this needs to be updated if you create more advice columns after this `FlexGateConfig` is created + // Warning: this needs to be updated if you create more advice columns after this `FlexGateConfig` is created max_rows: (1 << params.k) - meta.minimum_rows(), } } diff --git a/halo2-base/src/poseidon/hasher/tests/mod.rs b/halo2-base/src/poseidon/hasher/tests/mod.rs index a734f7d0..76087be2 100644 --- a/halo2-base/src/poseidon/hasher/tests/mod.rs +++ b/halo2-base/src/poseidon/hasher/tests/mod.rs @@ -11,18 +11,18 @@ mod state; fn test_mds() { let spec = OptimizedPoseidonSpec::::new::<8, 57, 0>(); - let mds = vec![ - vec![ + let mds = [ + [ "7511745149465107256748700652201246547602992235352608707588321460060273774987", "10370080108974718697676803824769673834027675643658433702224577712625900127200", "19705173408229649878903981084052839426532978878058043055305024233888854471533", ], - vec![ + [ "18732019378264290557468133440468564866454307626475683536618613112504878618481", "20870176810702568768751421378473869562658540583882454726129544628203806653987", "7266061498423634438633389053804536045105766754026813321943009179476902321146", ], - vec![ + [ "9131299761947733513298312097611845208338517739621853568979632113419485819303", "10595341252162738537912664445405114076324478519622938027420701542910180337937", "11597556804922396090267472882856054602429588299176362916247939723151043581408", diff --git a/halo2-ecc/src/secp256k1/tests/ecdsa_tests.rs b/halo2-ecc/src/secp256k1/tests/ecdsa_tests.rs index d3d47da7..c4002722 100644 --- a/halo2-ecc/src/secp256k1/tests/ecdsa_tests.rs +++ b/halo2-ecc/src/secp256k1/tests/ecdsa_tests.rs @@ -28,14 +28,18 @@ fn custom_parameters_ecdsa(sk: u64, msg_hash: u64, k: u64) -> ECDSAInput { } #[test] -#[should_panic(expected = "assertion failed: `(left == right)`")] +#[should_panic( + expected = "assertion `left == right` failed\n left: 0x0000000000000000000000000000000000000000000000000000000000000000\n right: 0x0000000000000000000000000000000000000000000000000000000000000001" +)] fn test_ecdsa_msg_hash_zero() { let input = custom_parameters_ecdsa(random::(), 0, random::()); run_test(input); } #[test] -#[should_panic(expected = "assertion failed: `(left == right)`")] +#[should_panic( + expected = "assertion `left == right` failed\n left: 0x0000000000000000000000000000000000000000000000000000000000000000\n right: 0x0000000000000000000000000000000000000000000000000000000000000001" +)] fn test_ecdsa_private_key_zero() { let input = custom_parameters_ecdsa(0, random::(), random::()); run_test(input); diff --git a/hashes/zkevm/Cargo.toml b/hashes/zkevm/Cargo.toml index c4d5425e..22945267 100644 --- a/hashes/zkevm/Cargo.toml +++ b/hashes/zkevm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zkevm-hashes" -version = "0.2.1" +version = "0.2.2" authors = ["Privacy Scaling Explorations Team", "Taiko Labs", "Intrinsic Technologies"] license = "MIT OR Apache-2.0" edition = "2021" @@ -23,7 +23,7 @@ rayon = "1.8" sha3 = "0.10.8" # always included but without features to use Native poseidon and get CircuitExt trait # snark-verifier-sdk = { version = "=0.1.7", default-features = false } -snark-verifier-sdk = { version = "=0.1.7", git = "https://github.com/axiom-crypto/snark-verifier.git", tag = "v0.1.7-git", default-features = false } +snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git", branch = "community-edition", default-features = false } getset = "0.1.2" type-map = "0.5.0" diff --git a/hashes/zkevm/src/keccak/component/circuit/tests/shard.rs b/hashes/zkevm/src/keccak/component/circuit/tests/shard.rs index 17726327..c41f4d70 100644 --- a/hashes/zkevm/src/keccak/component/circuit/tests/shard.rs +++ b/hashes/zkevm/src/keccak/component/circuit/tests/shard.rs @@ -175,7 +175,7 @@ fn test_prove_shard_circuit_commit() { circuit.set_base_circuit_break_points(break_points); let circuit_outputs = multi_inputs_to_circuit_outputs::(&inputs, circuit_params.capacity()); - let instances = vec![vec![calculate_circuit_outputs_commit(&circuit_outputs)]]; + let instances = [[calculate_circuit_outputs_commit(&circuit_outputs)]]; let proof = gen_proof_with_instances( ¶ms, diff --git a/rust-toolchain b/rust-toolchain index ee2d639b..36e57ce7 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2023-08-12 \ No newline at end of file +nightly-2024-02-08 From 5195ae692f501ccbe9dbb813a397a8b9ed960a0d Mon Sep 17 00:00:00 2001 From: i <0xisk@proton.me> Date: Fri, 29 Mar 2024 19:07:31 +0100 Subject: [PATCH 17/24] Fix some typos (#265) * chore: fixing typos * fix: lint issue --- halo2-base/README.md | 2 +- halo2-base/src/gates/circuit/builder.rs | 4 ++-- halo2-base/src/gates/flex_gate/mod.rs | 6 ++--- .../gates/flex_gate/threads/multi_phase.rs | 4 ++-- .../gates/flex_gate/threads/single_phase.rs | 2 +- halo2-base/src/gates/tests/bitwise_rotate.rs | 2 +- halo2-base/src/gates/tests/neg_prop.rs | 2 +- halo2-base/src/lib.rs | 2 +- halo2-base/src/poseidon/hasher/mds.rs | 2 +- .../src/poseidon/hasher/tests/hasher.rs | 22 ++++++++++--------- halo2-base/src/safe_types/mod.rs | 8 +++---- halo2-ecc/src/bigint/mod.rs | 2 +- halo2-ecc/src/ecc/mod.rs | 4 ++-- halo2-ecc/src/ecc/schnorr_signature.rs | 2 +- halo2-ecc/src/fields/mod.rs | 2 +- halo2-ecc/src/fields/native_fp.rs | 2 +- hashes/zkevm/src/keccak/README.md | 10 ++++----- .../src/keccak/component/circuit/shard.rs | 6 ++--- hashes/zkevm/src/keccak/component/output.rs | 2 +- .../src/keccak/vanilla/keccak_packed_multi.rs | 2 +- hashes/zkevm/src/keccak/vanilla/mod.rs | 6 ++--- hashes/zkevm/src/sha256/README.md | 4 ++-- 22 files changed, 50 insertions(+), 48 deletions(-) diff --git a/halo2-base/README.md b/halo2-base/README.md index 94cbbc58..3ba763ea 100644 --- a/halo2-base/README.md +++ b/halo2-base/README.md @@ -121,7 +121,7 @@ QuantumCell contains the following enum variants. Assigns an entirely new witness value into the advice column, such as a private input. When `assign_cell()` is called the value is wrapped in as an `Assigned::Trivial()` which marks it for exclusion from batch inversion. - **WitnessFraction**: - Assigns an entirely new witness value to the advice column. `WitnessFraction` exists for optimization purposes and accepts Assigned values wrapped in `Assigned::Rational()` marked for batch inverion (see [Assigned](#assigned)). + Assigns an entirely new witness value to the advice column. `WitnessFraction` exists for optimization purposes and accepts Assigned values wrapped in `Assigned::Rational()` marked for batch inversion (see [Assigned](#assigned)). - **Constant**: A value that is a "known" constant. A "known" refers to known at circuit creation time to both the Prover and Verifier. When you assign a constant value there exists another secret Fixed column in the circuit constraint table whose values are fixed at circuit creation time. When you assign a Constant value, you are adding this value to the Fixed column, adding the value as a witness to the Advice column, and then imposing an equality constraint between the two corresponding cells in the Fixed and Advice columns. diff --git a/halo2-base/src/gates/circuit/builder.rs b/halo2-base/src/gates/circuit/builder.rs index dabd50f1..ae7e188d 100644 --- a/halo2-base/src/gates/circuit/builder.rs +++ b/halo2-base/src/gates/circuit/builder.rs @@ -67,7 +67,7 @@ impl Default for BaseCircuitBuilder { impl BaseCircuitBuilder { /// Creates a new [BaseCircuitBuilder] with all default managers. /// * `witness_gen_only`: - /// * If true, the builder only does witness asignments and does not store constraint information -- this should only be used for the real prover. + /// * If true, the builder only does witness assignments and does not store constraint information -- this should only be used for the real prover. /// * If false, the builder also imposes constraints (selectors, fixed columns, copy constraints). Primarily used for keygen and mock prover (but can also be used for real prover). /// /// By default, **no** circuit configuration parameters have been set. @@ -254,7 +254,7 @@ impl BaseCircuitBuilder { /// Auto-calculates configuration parameters for the circuit and sets them. /// - /// * `k`: The number of in the circuit (i.e. numeber of rows = 2k) + /// * `k`: The number of in the circuit (i.e. number of rows = 2k) /// * `minimum_rows`: The minimum number of rows in the circuit that cannot be used for witness assignments and contain random `blinding factors` to ensure zk property, defaults to 0. /// * `lookup_bits`: The fixed lookup table will consist of [0, 2lookup_bits) pub fn calculate_params(&mut self, minimum_rows: Option) -> BaseCircuitParams { diff --git a/halo2-base/src/gates/flex_gate/mod.rs b/halo2-base/src/gates/flex_gate/mod.rs index 4ed3b4c3..82408e63 100644 --- a/halo2-base/src/gates/flex_gate/mod.rs +++ b/halo2-base/src/gates/flex_gate/mod.rs @@ -545,7 +545,7 @@ pub trait GateInstructions { ctx.last().unwrap() } - /// Constrains and returns `a & b`, assumeing `a` and `b` are boolean. + /// Constrains and returns `a & b`, assuming `a` and `b` are boolean. /// /// Defines a vertical gate of form | 0 | a | b | out |, where out = a * b. /// * `ctx`: [Context] to add the constraints to. @@ -590,7 +590,7 @@ pub trait GateInstructions { ctx.last().unwrap() } - /// Constrains and returns `!a` assumeing `a` is boolean. + /// Constrains and returns `!a` assuming `a` is boolean. /// /// Defines a vertical gate of form | 1 - a | a | 1 | 1 |, where 1 - a = out. /// * `ctx`: [Context] to add the constraints to. @@ -1204,7 +1204,7 @@ impl GateInstructions for GateChip { ctx.last().unwrap() } - /// Constains and returns `a || (b && c)`, assuming `a`, `b` and `c` are boolean. + /// Constrains and returns `a || (b && c)`, assuming `a`, `b` and `c` are boolean. /// /// Defines a vertical gate of form `| 1 - b c | b | c | 1 | a - 1 | 1 - b c | out | a - 1 | 1 | 1 | a |`, where out = a + b * c - a * b * c. /// * `ctx`: [Context] to add the constraints to diff --git a/halo2-base/src/gates/flex_gate/threads/multi_phase.rs b/halo2-base/src/gates/flex_gate/threads/multi_phase.rs index ae893fb1..44e3401f 100644 --- a/halo2-base/src/gates/flex_gate/threads/multi_phase.rs +++ b/halo2-base/src/gates/flex_gate/threads/multi_phase.rs @@ -29,7 +29,7 @@ impl MultiPhaseCoreManager { /// Creates a new [MultiPhaseCoreManager] with a default [SinglePhaseCoreManager] in phase 0. /// Creates an empty [SharedCopyConstraintManager] and sets `witness_gen_only` flag. /// * `witness_gen_only`: If true, the [MultiPhaseCoreManager] is used for witness generation only. - /// * If true, the gate thread builder only does witness asignments and does not store constraint information -- this should only be used for the real prover. + /// * If true, the gate thread builder only does witness assignments and does not store constraint information -- this should only be used for the real prover. /// * If false, the gate thread builder is used for keygen and mock prover (it can also be used for real prover) and the builder stores circuit information (e.g. copy constraints, fixed columns, enabled selectors). /// * These values are fixed for the circuit at key generation time, and they do not need to be re-computed by the prover in the actual proving phase. pub fn new(witness_gen_only: bool) -> Self { @@ -126,7 +126,7 @@ impl MultiPhaseCoreManager { /// Auto-calculates configuration parameters for the circuit /// - /// * `k`: The number of in the circuit (i.e. numeber of rows = 2k) + /// * `k`: The number of in the circuit (i.e. number of rows = 2k) /// * `minimum_rows`: The minimum number of rows in the circuit that cannot be used for witness assignments and contain random `blinding factors` to ensure zk property, defaults to 0. pub fn calculate_params(&self, k: usize, minimum_rows: Option) -> FlexGateConfigParams { let max_rows = (1 << k) - minimum_rows.unwrap_or(0); diff --git a/halo2-base/src/gates/flex_gate/threads/single_phase.rs b/halo2-base/src/gates/flex_gate/threads/single_phase.rs index a554d727..472ae999 100644 --- a/halo2-base/src/gates/flex_gate/threads/single_phase.rs +++ b/halo2-base/src/gates/flex_gate/threads/single_phase.rs @@ -42,7 +42,7 @@ pub struct SinglePhaseCoreManager { impl SinglePhaseCoreManager { /// Creates a new [SinglePhaseCoreManager] and spawns a main thread. /// * `witness_gen_only`: If true, the [SinglePhaseCoreManager] is used for witness generation only. - /// * If true, the gate thread builder only does witness asignments and does not store constraint information -- this should only be used for the real prover. + /// * If true, the gate thread builder only does witness assignments and does not store constraint information -- this should only be used for the real prover. /// * If false, the gate thread builder is used for keygen and mock prover (it can also be used for real prover) and the builder stores circuit information (e.g. copy constraints, fixed columns, enabled selectors). /// * These values are fixed for the circuit at key generation time, and they do not need to be re-computed by the prover in the actual proving phase. pub fn new(witness_gen_only: bool, copy_manager: SharedCopyConstraintManager) -> Self { diff --git a/halo2-base/src/gates/tests/bitwise_rotate.rs b/halo2-base/src/gates/tests/bitwise_rotate.rs index d854ffbe..e2a262d3 100644 --- a/halo2-base/src/gates/tests/bitwise_rotate.rs +++ b/halo2-base/src/gates/tests/bitwise_rotate.rs @@ -71,7 +71,7 @@ fn test_bitwise_rotate_gen( #[test] fn test_bitwise_rotate() { - // "<<" is leftroate. ">>" is rightrotate. + // "<<" is leftrotate. ">>" is rightrotate. // 1 << 8 == 256 test_bitwise_rotate_gen::<8, 10>(8, true, 1, 256, true); // 1 << 8 != 255 diff --git a/halo2-base/src/gates/tests/neg_prop.rs b/halo2-base/src/gates/tests/neg_prop.rs index 27994ac0..cc098bb0 100644 --- a/halo2-base/src/gates/tests/neg_prop.rs +++ b/halo2-base/src/gates/tests/neg_prop.rs @@ -101,7 +101,7 @@ fn arb_indicator(max_size: usize) -> impl Strategy bool { // check that: - // the length of the witnes array is correct + // the length of the witness array is correct // the sum of the witnesses is 1, indicting that there is only one index that is 1 if ind_witnesses.len() != len || ind_witnesses.iter().fold(Fr::zero(), |acc, val| acc + *val) != Fr::one() diff --git a/halo2-base/src/lib.rs b/halo2-base/src/lib.rs index 669bc1ad..ac2a3226 100644 --- a/halo2-base/src/lib.rs +++ b/halo2-base/src/lib.rs @@ -48,7 +48,7 @@ use virtual_region::copy_constraints::SharedCopyConstraintManager; pub mod gates; /// Module for the Poseidon hash function. pub mod poseidon; -/// Module for SafeType which enforce value range and realted functions. +/// Module for SafeType which enforce value range and related functions. pub mod safe_types; /// Utility functions for converting between different types of field elements. pub mod utils; diff --git a/halo2-base/src/poseidon/hasher/mds.rs b/halo2-base/src/poseidon/hasher/mds.rs index 91b7d262..5088a864 100644 --- a/halo2-base/src/poseidon/hasher/mds.rs +++ b/halo2-base/src/poseidon/hasher/mds.rs @@ -34,7 +34,7 @@ pub struct SparseMDSMatrix { pub(crate) col_hat: [F; RATE], } -/// `MDSMatrix` is applied to `State` to achive linear layer of Poseidon +/// `MDSMatrix` is applied to `State` to achieve linear layer of Poseidon #[derive(Clone, Debug)] pub struct MDSMatrix(pub(crate) Mds); diff --git a/halo2-base/src/poseidon/hasher/tests/hasher.rs b/halo2-base/src/poseidon/hasher/tests/hasher.rs index 7b55c3c4..78951bb6 100644 --- a/halo2-base/src/poseidon/hasher/tests/hasher.rs +++ b/halo2-base/src/poseidon/hasher/tests/hasher.rs @@ -22,7 +22,7 @@ struct Payload { } // check if the results from hasher and native sponge are same for hash_var_len_array. -fn hasher_compatiblity_verification< +fn hasher_compatibility_verification< const T: usize, const RATE: usize, const R_F: usize, @@ -50,7 +50,7 @@ fn hasher_compatiblity_verification< } // check if the results from hasher and native sponge are same for hash_compact_input. -fn hasher_compact_inputs_compatiblity_verification< +fn hasher_compact_inputs_compatibility_verification< const T: usize, const RATE: usize, const R_F: usize, @@ -115,7 +115,7 @@ fn hasher_compact_inputs_compatiblity_verification< } // check if the results from hasher and native sponge are same for hash_compact_input. -fn hasher_compact_chunk_inputs_compatiblity_verification< +fn hasher_compact_chunk_inputs_compatibility_verification< const T: usize, const RATE: usize, const R_F: usize, @@ -189,7 +189,7 @@ fn random_payload_without_len(max_len: usize, max_value: usize) } #[test] -fn test_poseidon_hasher_compatiblity() { +fn test_poseidon_hasher_compatibility() { { const T: usize = 3; const RATE: usize = 2; @@ -216,7 +216,7 @@ fn test_poseidon_hasher_compatiblity() { random_payload(RATE * 2 + 1, RATE * 2 + 1, usize::MAX), random_payload(RATE * 5 + 1, RATE * 5 + 1, usize::MAX), ]; - hasher_compatiblity_verification::(payloads); + hasher_compatibility_verification::(payloads); } } @@ -262,7 +262,9 @@ fn test_poseidon_hasher_compact_inputs() { random_payload(RATE * 5, RATE * 5, usize::MAX), ]; base_test().k(12).run(|ctx, range| { - hasher_compact_inputs_compatiblity_verification::(payloads, ctx, range); + hasher_compact_inputs_compatibility_verification::( + payloads, ctx, range, + ); }); } } @@ -289,7 +291,7 @@ fn test_poseidon_hasher_compact_inputs_with_prover() { .collect::>(); base_test().k(12).bench_builder(init_payloads, logic_payloads, |pool, range, input| { let ctx = pool.main(); - hasher_compact_inputs_compatiblity_verification::(input, ctx, range); + hasher_compact_inputs_compatibility_verification::(input, ctx, range); }); } } @@ -306,7 +308,7 @@ fn test_poseidon_hasher_compact_chunk_inputs() { (random_payload(RATE * 3, RATE * 3, usize::MAX), true), ]; base_test().k(12).run(|ctx, range| { - hasher_compact_chunk_inputs_compatiblity_verification::( + hasher_compact_chunk_inputs_compatibility_verification::( payloads, ctx, range, ); }); @@ -320,7 +322,7 @@ fn test_poseidon_hasher_compact_chunk_inputs() { (random_payload(0, 0, usize::MAX), false), ]; base_test().k(12).run(|ctx, range| { - hasher_compact_chunk_inputs_compatiblity_verification::( + hasher_compact_chunk_inputs_compatibility_verification::( payloads, ctx, range, ); }); @@ -349,7 +351,7 @@ fn test_poseidon_hasher_compact_chunk_inputs_with_prover() { .collect::>(); base_test().k(12).bench_builder(init_payloads, logic_payloads, |pool, range, input| { let ctx = pool.main(); - hasher_compact_chunk_inputs_compatiblity_verification::( + hasher_compact_chunk_inputs_compatibility_verification::( input, ctx, range, ); }); diff --git a/halo2-base/src/safe_types/mod.rs b/halo2-base/src/safe_types/mod.rs index 205c314e..98485637 100644 --- a/halo2-base/src/safe_types/mod.rs +++ b/halo2-base/src/safe_types/mod.rs @@ -34,7 +34,7 @@ const BITS_PER_BYTE: usize = 8; /// where each [`AssignedValue`] represents 1 byte. However, the range of [`AssignedValue`] is much /// larger than 1 byte(0~255). If a circuit takes 32 [`AssignedValue`] as inputs and some of them /// are actually greater than 255, there could be some undefined behaviors. -/// [`SafeType`] gurantees the value range of its owned [`AssignedValue`]. So circuits don't need to +/// [`SafeType`] guarantees the value range of its owned [`AssignedValue`]. So circuits don't need to /// do any extra value checking if they take SafeType as inputs. /// - `TOTAL_BITS` is the number of total bits of this type. /// - `BYTES_PER_ELE` is the number of bytes of each element. @@ -131,7 +131,7 @@ impl<'a, F: ScalarField> SafeTypeChip<'a, F> { /// Convert a vector of AssignedValue (treated as little-endian) to a SafeType. /// The number of bytes of inputs must equal to the number of bytes of outputs. - /// This function also add contraints that a AssignedValue in inputs must be in the range of a byte. + /// This function also add constraints that a AssignedValue in inputs must be in the range of a byte. pub fn raw_bytes_to( &self, ctx: &mut Context, @@ -276,7 +276,7 @@ impl<'a, F: ScalarField> SafeTypeChip<'a, F> { /// /// * inputs: Vector representing the byte array, right padded to `max_len`. See [VarLenBytesVec] for details about padding. /// * len: [`AssignedValue`] witness representing the variable length of the byte array. Constrained to be `<= max_len`. - /// * max_len: [usize] representing the maximum length of the byte array and the number of elements it must contain. We enforce this to be provided explictly to make sure length of `inputs` is determinstic. + /// * max_len: [usize] representing the maximum length of the byte array and the number of elements it must contain. We enforce this to be provided explicitly to make sure length of `inputs` is deterministic. /// /// ## Assumptions /// * `max_len < u64::MAX` to prevent overflow (but you should never make an array this large) @@ -311,7 +311,7 @@ impl<'a, F: ScalarField> SafeTypeChip<'a, F> { /// Converts a slice of AssignedValue(treated as little-endian) to FixLenBytesVec. /// /// * inputs: Slice representing the byte array. - /// * len: length of the byte array. We enforce this to be provided explictly to make sure length of `inputs` is determinstic. + /// * len: length of the byte array. We enforce this to be provided explicitly to make sure length of `inputs` is deterministic. pub fn raw_to_fix_len_bytes_vec( &self, ctx: &mut Context, diff --git a/halo2-ecc/src/bigint/mod.rs b/halo2-ecc/src/bigint/mod.rs index 37c32ecf..c7965adf 100644 --- a/halo2-ecc/src/bigint/mod.rs +++ b/halo2-ecc/src/bigint/mod.rs @@ -125,7 +125,7 @@ impl FixedOverflowInteger { /// Input: a BigInteger `value`, Output: the `FixedOverflowInteger` that represents the same value /// Can handle signs - /// Note the representation of the integer will be in proper (no overflow) format, if signs are interpretted correctly + /// Note the representation of the integer will be in proper (no overflow) format, if signs are interpreted correctly pub fn from_native(value: &BigUint, num_limbs: usize, limb_bits: usize) -> Self { let limbs = decompose_biguint(value, num_limbs, limb_bits); Self { limbs } diff --git a/halo2-ecc/src/ecc/mod.rs b/halo2-ecc/src/ecc/mod.rs index b410b1e0..65cec232 100644 --- a/halo2-ecc/src/ecc/mod.rs +++ b/halo2-ecc/src/ecc/mod.rs @@ -415,7 +415,7 @@ where EcPoint::new(Rx, Ry) } -// takes the dot product of points with sel, where each is intepreted as +// takes the dot product of points with sel, where each is interpreted as // a _vector_ pub fn ec_select_by_indicator( chip: &FC, @@ -635,7 +635,7 @@ where // need to supply an extra generic `C` implementing `CurveAffine` trait in order to generate random witness points on the curve in question // Using Simultaneous 2^w-Ary Method, see https://www.bmoeller.de/pdf/multiexp-sac2001.pdf -// Random Accumlation point trick learned from halo2wrong: https://hackmd.io/ncuKqRXzR-Cw-Au2fGzsMg?view +// Random Accumulation point trick learned from halo2wrong: https://hackmd.io/ncuKqRXzR-Cw-Au2fGzsMg?view // Input: // - `scalars` is vector of same length as `P` // - each `scalar` in `scalars` satisfies same assumptions as in `scalar_multiply` above diff --git a/halo2-ecc/src/ecc/schnorr_signature.rs b/halo2-ecc/src/ecc/schnorr_signature.rs index a124560f..85b42c02 100644 --- a/halo2-ecc/src/ecc/schnorr_signature.rs +++ b/halo2-ecc/src/ecc/schnorr_signature.rs @@ -63,7 +63,7 @@ where let x_neq = base_chip.gate().not(ctx, x_eq); // R = s⋅G - e⋅P - // R is not infinity point implicitly constrainted by is_strict = true + // R is not infinity point implicitly constrained by is_strict = true let R = chip.sub_unequal(ctx, s_G, e_P, true); // check R.y is even diff --git a/halo2-ecc/src/fields/mod.rs b/halo2-ecc/src/fields/mod.rs index 469397df..de79dea2 100644 --- a/halo2-ecc/src/fields/mod.rs +++ b/halo2-ecc/src/fields/mod.rs @@ -61,7 +61,7 @@ pub trait FieldChip: Clone + Send + Sync { /// Assigns `fe` as private witness. Note that the witness may **not** be constrained to be a unique representation of the field element `fe`. fn load_private(&self, ctx: &mut Context, fe: Self::FieldType) -> Self::FieldPoint; - /// Assigns `fe` as private witness and contrains the witness to be in reduced form. + /// Assigns `fe` as private witness and constrains the witness to be in reduced form. fn load_private_reduced( &self, ctx: &mut Context, diff --git a/halo2-ecc/src/fields/native_fp.rs b/halo2-ecc/src/fields/native_fp.rs index 7391d1db..bb3f70b4 100644 --- a/halo2-ecc/src/fields/native_fp.rs +++ b/halo2-ecc/src/fields/native_fp.rs @@ -145,7 +145,7 @@ impl<'range, F: BigPrimeField> FieldChip for NativeFieldChip<'range, F> { a: impl Into>, max_bits: usize, // the maximum bits that a.value could take ) { - // skip range chek if max_bits >= F::NUM_BITS + // skip range check if max_bits >= F::NUM_BITS if max_bits < F::NUM_BITS as usize { let a: AssignedValue = a.into(); self.range().range_check(ctx, a, max_bits); diff --git a/hashes/zkevm/src/keccak/README.md b/hashes/zkevm/src/keccak/README.md index 527d671f..89c838a9 100644 --- a/hashes/zkevm/src/keccak/README.md +++ b/hashes/zkevm/src/keccak/README.md @@ -4,13 +4,13 @@ Keccak circuit in vanilla halo2. This implementation starts from [PSE version](https://github.com/privacy-scaling-explorations/zkevm-circuits/tree/main/zkevm-circuits/src/keccak_circuit), then adopts some changes from [this PR](https://github.com/scroll-tech/zkevm-circuits/pull/216) and later updates in PSE version. -The major differences is that this version directly represent raw inputs and Keccak results as witnesses, while the original version only has RLCs(random linear combination) of raw inputs and Keccak results. Because this version doesn't need RLCs, it doesn't have the 2nd phase or use challenge APIs. +The major difference is that this version directly represent raw inputs and Keccak results as witnesses, while the original version only has RLCs(random linear combination) of raw inputs and Keccak results. Because this version doesn't need RLCs, it doesn't have the 2nd phase or use challenge APIs. ### Logical Input/Output Logically the circuit takes an array of bytes as inputs and Keccak results of these bytes as outputs. -`keccak::vanilla::witness::multi_keccak` generates the witnesses of the ciruit for a given input. +`keccak::vanilla::witness::multi_keccak` generates the witnesses of the circuit for a given input. ### Background Knowledge @@ -23,8 +23,8 @@ All these items remain consistent across all versions. - Every input is padded to be a multiple of RATE (136 bytes). If the length of the logical input already matches a multiple of RATE, an additional RATE bytes are added as padding. - Each `keccak_f` absorbs `RATE` bytes, which are splitted into `NUM_WORDS_TO_ABSORB`(17) words. Each word has `NUM_BYTES_PER_WORD`(8) bytes. - Each of the first `NUM_WORDS_TO_ABSORB`(17) rounds of each `keccak_f` absorbs a word. -- `is_final`(anothe name is `is_enabled`) is meaningful only at the first row of the "squeeze" round. It must be true if this is the last `keccak_f` of an logical input. -- The first round of the circuit is a dummy round, which doesn't crespond to any input. +- `is_final`(anothe name is `is_enabled`) is meaningful only at the first row of the "squeeze" round. It must be true if this is the last `keccak_f` of a logical input. +- The first round of the circuit is a dummy round, which doesn't correspond to any input. ### Raw inputs @@ -73,7 +73,7 @@ Let's say `rows_per_round = 10` and `inputs = [[], [0x89, 0x88, .., 0x01]]`. The - Removed column `output_rlc` and related gates. - Removed challenges. - Refactored the folder structure to follow [Scroll's repo](https://github.com/scroll-tech/zkevm-circuits/tree/95f82762cfec46140d6866c34a420ee1fc1e27c7/zkevm-circuits/src/keccak_circuit). `mod.rs` and `witness.rs` could be found [here](https://github.com/scroll-tech/zkevm-circuits/blob/develop/zkevm-circuits/src/keccak_circuit.rs). `KeccakTable` could be found [here](https://github.com/scroll-tech/zkevm-circuits/blob/95f82762cfec46140d6866c34a420ee1fc1e27c7/zkevm-circuits/src/table.rs#L1308). -- Imported utilites from [PSE zkevm-circuits repo](https://github.com/privacy-scaling-explorations/zkevm-circuits/blob/588b8b8c55bf639fc5cbf7eae575da922ea7f1fd/zkevm-circuits/src/util/word.rs). +- Imported utilities from [PSE zkevm-circuits repo](https://github.com/privacy-scaling-explorations/zkevm-circuits/blob/588b8b8c55bf639fc5cbf7eae575da922ea7f1fd/zkevm-circuits/src/util/word.rs). ## Component diff --git a/hashes/zkevm/src/keccak/component/circuit/shard.rs b/hashes/zkevm/src/keccak/component/circuit/shard.rs index 604da477..e0ffddc8 100644 --- a/hashes/zkevm/src/keccak/component/circuit/shard.rs +++ b/hashes/zkevm/src/keccak/component/circuit/shard.rs @@ -71,7 +71,7 @@ pub struct KeccakComponentShardCircuitParams { // Number of unusable rows withhold by Halo2. #[getset(get_copy = "pub")] num_unusable_row: usize, - /// Max keccak_f this circuits can aceept. The circuit can at most process `capacity` of inputs + /// Max keccak_f this circuits can accept. The circuit can at most process `capacity` of inputs /// with < NUM_BYTES_TO_ABSORB bytes or an input with `capacity * NUM_BYTES_TO_ABSORB - 1` bytes. #[getset(get_copy = "pub")] capacity: usize, @@ -410,7 +410,7 @@ pub(crate) fn create_hasher() -> PoseidonHasher( ctx: &mut Context, gate: &impl GateInstructions, @@ -466,7 +466,7 @@ pub fn pack_inputs_from_keccak_fs( /// Encode raw inputs from Keccak circuit witnesses into lookup keys. /// -/// Each element in the return value corrresponds to a Keccak chunk. If is_final = true, this element is the lookup key of the corresponding logical input. +/// Each element in the return value corresponds to a Keccak chunk. If is_final = true, this element is the lookup key of the corresponding logical input. pub fn encode_inputs_from_keccak_fs( ctx: &mut Context, gate: &impl GateInstructions, diff --git a/hashes/zkevm/src/keccak/component/output.rs b/hashes/zkevm/src/keccak/component/output.rs index 22688b5f..5787bdc4 100644 --- a/hashes/zkevm/src/keccak/component/output.rs +++ b/hashes/zkevm/src/keccak/component/output.rs @@ -19,7 +19,7 @@ pub struct KeccakCircuitOutput { pub hash_hi: E, } -/// Return circuit outputs of the specified Keccak corprocessor circuit for a specified input. +/// Return circuit outputs of the specified Keccak coprocessor circuit for a specified input. pub fn multi_inputs_to_circuit_outputs( inputs: &[Vec], capacity: usize, diff --git a/hashes/zkevm/src/keccak/vanilla/keccak_packed_multi.rs b/hashes/zkevm/src/keccak/vanilla/keccak_packed_multi.rs index 6a78efc9..d149e982 100644 --- a/hashes/zkevm/src/keccak/vanilla/keccak_packed_multi.rs +++ b/hashes/zkevm/src/keccak/vanilla/keccak_packed_multi.rs @@ -489,7 +489,7 @@ pub(crate) mod transform { } } -// Transfroms values to cells +// Transforms values to cells pub(crate) mod transform_to { use crate::{ halo2_proofs::plonk::{ConstraintSystem, TableColumn}, diff --git a/hashes/zkevm/src/keccak/vanilla/mod.rs b/hashes/zkevm/src/keccak/vanilla/mod.rs index c049ed89..8faa6d7b 100644 --- a/hashes/zkevm/src/keccak/vanilla/mod.rs +++ b/hashes/zkevm/src/keccak/vanilla/mod.rs @@ -266,7 +266,7 @@ impl KeccakCircuitConfig { // that allows reusing the same parts in an optimal way for the chi step. // We can save quite a few columns by not recombining the parts after rho/pi and // re-splitting the words again before chi. Instead we do chi directly - // on the output parts of rho/pi. For rho/pi specically we do + // on the output parts of rho/pi. For rho/pi specially we do // `s[j][2 * i + 3 * j) % 5] = normalize(rot(s[i][j], RHOM[i][j]))`. cell_manager.start_region(); let mut lookup_counter = 0; @@ -278,7 +278,7 @@ impl KeccakCircuitConfig { // multiple rows with lookups in a way that doesn't require any // extra additional cells or selectors we have to put all `s[i]`'s on the same // row. This isn't that strong of a requirement actually because we the - // words are split into multipe parts, and so only the parts at the same + // words are split into multiple parts, and so only the parts at the same // position of those words need to be on the same row. let target_word_sizes = target_part_sizes(part_size); let num_word_parts = target_word_sizes.len(); @@ -637,7 +637,7 @@ impl KeccakCircuitConfig { // Logically here we want !q_input[cur] && !start_new_hash(cur) ==> bytes_left[cur + num_rows_per_round] == bytes_left[cur] // In practice, in order to save a degree we use !(q_input[cur] ^ start_new_hash(cur)) ==> bytes_left[cur + num_rows_per_round] == bytes_left[cur] // When q_input[cur] is true, the above constraint q_input[cur] ==> bytes_left[cur + num_rows_per_round] + word_len == bytes_left[cur] has - // already been enabled. Even is_final in start_new_hash(cur) is true, it's just over-constrainted. + // already been enabled. Even is_final in start_new_hash(cur) is true, it's just over-constrained. // Note: At the first row of any round except the last round, is_final could be either true or false. cb.condition(not::expr(q(q_input, meta) + start_new_hash(meta, Rotation::cur())), |cb| { let bytes_left_next_expr = diff --git a/hashes/zkevm/src/sha256/README.md b/hashes/zkevm/src/sha256/README.md index 058cb371..23ed9fe3 100644 --- a/hashes/zkevm/src/sha256/README.md +++ b/hashes/zkevm/src/sha256/README.md @@ -4,14 +4,14 @@ SHA-256 circuit in vanilla halo2. This implementation is largely based on [Brechtpd](https://github.com/Brechtpd)'s [PR](https://github.com/privacy-scaling-explorations/zkevm-circuits/pull/756) to the PSE `zkevm-circuits`. His implementation of SHA-256 is in turn based on his implementation of Keccak using the "Bits" approach: one can read more about it [here](https://hackmd.io/NaTuIvmaQCybaOYgd-DG1Q?view#Bit-implementation). -The major differences is that this version directly represent raw inputs and SHA-256 digests as witnesses, while the original version only has RLCs (random linear combination) of raw inputs and outputs. Because this version doesn't need RLCs, it doesn't have the 2nd phase or use challenge APIs. +The major difference is that this version directly represent raw inputs and SHA-256 digests as witnesses, while the original version only has RLCs (random linear combination) of raw inputs and outputs. Because this version doesn't need RLCs, it doesn't have the 2nd phase or use challenge APIs. ### Logical Input/Output Logically the circuit takes a variable length array of variable length bytes as inputs and SHA-256 digests of these bytes as outputs. While these logical inputs are variable, what is fixed in a given circuit is max number of _total number of SHA-256 input blocks_ that can be processed (see below). We refer to this as the capacity of the circuit. -`sha256::vanilla::witness::generate_witnesses_multi_sha256` generates the witnesses of the ciruit for a given input. +`sha256::vanilla::witness::generate_witnesses_multi_sha256` generates the witnesses of the circuit for a given input. ### Background Knowledge From 5ce9ecf1dd676cad6a3055b1c0a0aa5bbeab2894 Mon Sep 17 00:00:00 2001 From: goofylfg <165781272+goofylfg@users.noreply.github.com> Date: Tue, 16 Apr 2024 14:16:44 +0800 Subject: [PATCH 18/24] chore: fix typo (#267) * chore:fix typo * chore:fix typo --- hashes/zkevm/src/keccak/component/circuit/shard.rs | 2 +- hashes/zkevm/src/util/word.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hashes/zkevm/src/keccak/component/circuit/shard.rs b/hashes/zkevm/src/keccak/component/circuit/shard.rs index e0ffddc8..e35d473b 100644 --- a/hashes/zkevm/src/keccak/component/circuit/shard.rs +++ b/hashes/zkevm/src/keccak/component/circuit/shard.rs @@ -96,7 +96,7 @@ impl KeccakComponentShardCircuitParams { let max_rows = (1 << k) - num_unusable_row; // Derived from [crate::keccak::vanilla::keccak_packed_multi::get_keccak_capacity]. let rows_per_round = max_rows / (capacity * (NUM_ROUNDS + 1) + 1 + NUM_WORDS_TO_ABSORB); - assert!(rows_per_round > 0, "No enough rows for the speficied capacity"); + assert!(rows_per_round > 0, "No enough rows for the specified capacity"); let keccak_circuit_params = KeccakConfigParams { k: k as u32, rows_per_round }; let base_circuit_params = BaseCircuitParams { k, diff --git a/hashes/zkevm/src/util/word.rs b/hashes/zkevm/src/util/word.rs index 9d91f5ee..e466eb7e 100644 --- a/hashes/zkevm/src/util/word.rs +++ b/hashes/zkevm/src/util/word.rs @@ -1,5 +1,5 @@ //! Define generic Word type with utility functions -// Naming Convesion +// Naming conversion // - Limbs: An EVM word is 256 bits **big-endian**. Limbs N means split 256 into N limb. For example, N = 4, each // limb is 256/4 = 64 bits From 957445b838c4415bb22aece909d0cfc879beffad Mon Sep 17 00:00:00 2001 From: yanziseeker <153156292+AdventureSeeker987@users.noreply.github.com> Date: Sat, 27 Apr 2024 07:25:44 +0800 Subject: [PATCH 19/24] chore(all):fix typos (#268) * Update mod.rs * Update mod.rs * Update fixed_base.rs * Update mod.rs * Update bytes.rs --- halo2-base/src/poseidon/hasher/mod.rs | 2 +- halo2-base/src/safe_types/tests/bytes.rs | 2 +- halo2-base/src/utils/mod.rs | 2 +- halo2-ecc/src/ecc/fixed_base.rs | 2 +- halo2-ecc/src/ecc/mod.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/halo2-base/src/poseidon/hasher/mod.rs b/halo2-base/src/poseidon/hasher/mod.rs index 68cf64c6..035862d5 100644 --- a/halo2-base/src/poseidon/hasher/mod.rs +++ b/halo2-base/src/poseidon/hasher/mod.rs @@ -243,7 +243,7 @@ impl PoseidonHasher, SafeTypeChip<'_, Fr>)>(mut f: FM) { base_test().k(10).lookup_bits(8).run(|ctx, range| { let safe = SafeTypeChip::new(range); diff --git a/halo2-base/src/utils/mod.rs b/halo2-base/src/utils/mod.rs index 2aaa5166..87404349 100644 --- a/halo2-base/src/utils/mod.rs +++ b/halo2-base/src/utils/mod.rs @@ -62,7 +62,7 @@ pub trait ScalarField: PrimeField + FromUniformBytes<64> + From + Hash + O /// Creates a field element from a little endian byte representation. /// /// The default implementation assumes that `PrimeField::from_repr` is implemented for little-endian. - /// It should be overriden if this is not the case. + /// It should be overridden if this is not the case. fn from_bytes_le(bytes: &[u8]) -> Self { let mut repr = Self::Repr::default(); repr.as_mut()[..bytes.len()].copy_from_slice(bytes); diff --git a/halo2-ecc/src/ecc/fixed_base.rs b/halo2-ecc/src/ecc/fixed_base.rs index 304cd6b8..936b0efb 100644 --- a/halo2-ecc/src/ecc/fixed_base.rs +++ b/halo2-ecc/src/ecc/fixed_base.rs @@ -208,7 +208,7 @@ where }, ); let ctx = builder.main(); - // sum `scalar_mults` but take into account possiblity of identity points + // sum `scalar_mults` but take into account possibility of identity points let any_point2 = chip.load_random_point::(ctx); let mut acc = any_point2.clone(); for point in scalar_mults { diff --git a/halo2-ecc/src/ecc/mod.rs b/halo2-ecc/src/ecc/mod.rs index 65cec232..703a4305 100644 --- a/halo2-ecc/src/ecc/mod.rs +++ b/halo2-ecc/src/ecc/mod.rs @@ -1090,7 +1090,7 @@ where if radix == 0 { radix = 1; }*/ - // guessing that is is always better to use parallelism for >25 points + // guessing that is always better to use parallelism for >25 points pippenger::multi_exp_par::( self.field_chip, builder, From 72037c8827a93cf6b6a93ef0d4593955cf70da8f Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Fri, 17 May 2024 07:54:44 +0530 Subject: [PATCH 20/24] fix: mod_inverse bug --- .../secp256k1/hash_to_curve/map_to_curve.rs | 6 ++--- halo2-ecc/src/secp256k1/hash_to_curve/mod.rs | 27 +++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 66566af1..917f1610 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -1,6 +1,6 @@ use halo2_base::{ gates::{GateInstructions, RangeInstructions}, - halo2_proofs::halo2curves::secq256k1::Fq as Fp, + halo2_proofs::{arithmetic::Field, halo2curves::secp256k1::Fp}, utils::{BigPrimeField, ScalarField}, Context, }; @@ -54,7 +54,7 @@ fn mod_inverse( num: &ProperCrtUint, ) -> ProperCrtUint { let one = ctx.load_constant(F::ONE); - let one_int = fp_chip.load_constant_uint(ctx, BigUint::from(1u64)); + let one_int = fp_chip.load_constant(ctx, Fp::ONE); let p = fp_chip.p.to_biguint().unwrap(); let p_minus_two = p.clone() - 2u64; @@ -63,7 +63,7 @@ fn mod_inverse( let inverse_native = num_native.modpow(&p_minus_two, &p); assert_eq!((num_native * inverse_native.clone()) % p, BigUint::from(1u64)); - let mod_inverse = fp_chip.load_constant_uint(ctx, inverse_native); + let mod_inverse = fp_chip.load_private(ctx, Fp::from_bytes_le(&inverse_native.to_bytes_le())); let is_one = fp_chip.mul(ctx, num, &mod_inverse); let is_equal = fp_chip.is_equal(ctx, is_one, one_int); assert_eq!(is_equal.value(), &F::ONE); diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs index cc87e2ed..f6a185b6 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/mod.rs @@ -41,7 +41,7 @@ pub fn hash_to_curve( #[cfg(test)] mod test { - use halo2_base::{halo2_proofs::halo2curves::grumpkin::Fq as Fr, utils::testing::base_test}; + use halo2_base::{halo2_proofs::halo2curves::bn256::Fr, utils::testing::base_test}; use crate::{ ecc::EccChip, @@ -50,6 +50,7 @@ mod test { use super::hash_to_curve; + #[derive(Debug, Default, Clone)] struct TestData { message: String, point: (String, String), @@ -119,14 +120,18 @@ mod test { } ]; - base_test().k(15).lookup_bits(14).expect_satisfied(true).run(|ctx, range| { - let fp_chip = FpChip::::new(range, 88, 3); - let ecc_chip = EccChip::>::new(&fp_chip); + base_test().k(15).lookup_bits(14).expect_satisfied(true).bench_builder( + TestData::default(), + test_data[2].clone(), + |pool, range, _: TestData| { + let ctx = pool.main(); - let sha256_chip = Sha256Chip::new(range); + let fp_chip = FpChip::::new(range, 88, 3); + let ecc_chip = EccChip::>::new(&fp_chip); - for i in 0..test_data.len() { - let msg_bytes = test_data[i] + let sha256_chip = Sha256Chip::new(range); + + let msg_bytes = test_data[2] .message .as_bytes() .iter() @@ -135,9 +140,9 @@ mod test { let point = hash_to_curve(ctx, &ecc_chip, &sha256_chip, msg_bytes.as_slice()); - assert_eq!(point.x.value().to_str_radix(16), test_data[i].point.0); - assert_eq!(point.y.value().to_str_radix(16), test_data[i].point.1); - } - }); + assert_eq!(point.x.value().to_str_radix(16), test_data[2].point.0); + assert_eq!(point.y.value().to_str_radix(16), test_data[2].point.1); + }, + ); } } From ce6750636d70801c90caee5924dfbe1ad145091d Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Fri, 14 Jun 2024 10:19:24 +0530 Subject: [PATCH 21/24] fix: added check on p for sqrt --- halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 917f1610..82742197 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -78,6 +78,8 @@ pub(crate) fn sqrt( num: &ProperCrtUint, ) -> ProperCrtUint { let p = fp_chip.p.to_biguint().unwrap(); + assert_eq!(&p % 4u64, BigUint::from(3u64), "p must be congruent to 3 mod 4"); + let p_plus_1 = p.clone() + 1u64; let p_plus_1_by_4 = p_plus_1 / 4u64; From b7f4960df02e09e17422da6cc914c2233e4814be Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Fri, 21 Jun 2024 11:34:47 +0530 Subject: [PATCH 22/24] fix: sha256 init_state in fixed column --- halo2-ecc/src/secp256k1/sha256/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2-ecc/src/secp256k1/sha256/mod.rs b/halo2-ecc/src/secp256k1/sha256/mod.rs index 173599d2..6565933d 100644 --- a/halo2-ecc/src/secp256k1/sha256/mod.rs +++ b/halo2-ecc/src/secp256k1/sha256/mod.rs @@ -95,7 +95,7 @@ impl<'a, F: BigPrimeField> Sha256Chip<'a, F> { let mut assigned_last_state_vec = vec![last_state .iter() - .map(|state| ctx.load_witness(F::from(*state as u64))) + .map(|state| ctx.load_constant(F::from(*state as u64))) .collect_vec()]; let mut num_processed_input = 0; From 243f778f6468f7a209c8be75fa9a61e13e8ff63b Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Fri, 21 Jun 2024 23:35:23 +0530 Subject: [PATCH 23/24] fix: xy2_selector --- halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs index 82742197..0cf9c1f1 100644 --- a/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs +++ b/halo2-ecc/src/secp256k1/hash_to_curve/map_to_curve.rs @@ -26,21 +26,10 @@ fn xy2_selector( x1: &ProperCrtUint, x2: &ProperCrtUint, ) -> (ProperCrtUint, ProperCrtUint) { - let gate = fp_chip.range().gate(); - let one = ctx.load_constant(F::ONE); - let gx1_sqrt = sqrt(ctx, fp_chip, gx1); - let gx2_sqrt = sqrt(ctx, fp_chip, gx2); - let sq_gx1_sqrt = fp_chip.mul(ctx, &gx1_sqrt, &gx1_sqrt); - let sq_gx2_sqrt = fp_chip.mul(ctx, &gx2_sqrt, &gx2_sqrt); let s1 = fp_chip.is_equal(ctx, &sq_gx1_sqrt, gx1); - let s2 = fp_chip.is_equal(ctx, &sq_gx2_sqrt, gx2); - - let _one = gate.add(ctx, s1, s2); - assert_eq!(_one.value(), &F::ONE); - ctx.constrain_equal(&_one, &one); let x = fp_chip.select(ctx, x1.into(), x2.into(), s1); let y2 = fp_chip.select(ctx, gx1.into(), gx2.into(), s1); From 3cd064fcffe574340925985dc901e296a06b28d5 Mon Sep 17 00:00:00 2001 From: shreyas-londhe Date: Fri, 28 Jun 2024 12:20:14 +0530 Subject: [PATCH 24/24] docs: added acknowledgement --- halo2-ecc/src/secp256k1/sha256/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/halo2-ecc/src/secp256k1/sha256/mod.rs b/halo2-ecc/src/secp256k1/sha256/mod.rs index 6565933d..70a4407b 100644 --- a/halo2-ecc/src/secp256k1/sha256/mod.rs +++ b/halo2-ecc/src/secp256k1/sha256/mod.rs @@ -1,3 +1,5 @@ +// ! This file is a modified version of the original file from https://github.com/ChainSafe/Spectre (sha256-flex) (GPL-3.0 license) + use halo2_base::{ gates::{GateInstructions, RangeChip, RangeInstructions}, halo2_proofs::plonk::Error,