diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index e493b0af..4232379a 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -1,9 +1,11 @@ +use ff::PrimeFieldBits; use halo2::{ circuit::{Cell, Layouter, Region}, plonk::{Advice, Column, Error, Permutation}, }; use pasta_curves::arithmetic::FieldExt; use std::array; +use std::convert::TryInto; pub(crate) mod cond_swap; pub(crate) mod enable_flag; @@ -97,3 +99,27 @@ pub fn transpose_option_array( } ret } + +/// Subsets a field element to a specified bitrange (little-endian) +pub fn bitrange_subset( + field_elem: F, + bitrange: std::ops::Range, +) -> F { + assert!(bitrange.end <= F::NUM_BITS as usize); + + let bits: Vec = field_elem + .to_le_bits() + .iter() + .by_val() + .skip(bitrange.start) + .take(bitrange.end - bitrange.start) + .chain(std::iter::repeat(false)) + .take(256) + .collect(); + let bytearray: Vec = bits + .chunks_exact(8) + .map(|byte| byte.iter().rev().fold(0u8, |acc, bit| acc * 2 + *bit as u8)) + .collect(); + + F::from_bytes(&bytearray.try_into().unwrap()).unwrap() +}