2022-08-29 18:10:51 -07:00
|
|
|
use std::mem::{size_of, transmute_copy, ManuallyDrop};
|
|
|
|
|
|
2022-09-29 13:45:46 -06:00
|
|
|
use ethereum_types::{H160, H256, U256};
|
2022-05-04 20:57:07 +02:00
|
|
|
use itertools::Itertools;
|
2022-06-27 07:18:21 -07:00
|
|
|
use plonky2::field::extension::Extendable;
|
2022-06-27 15:07:52 -07:00
|
|
|
use plonky2::field::packed::PackedField;
|
2022-05-04 20:57:07 +02:00
|
|
|
use plonky2::field::polynomial::PolynomialValues;
|
2022-06-27 12:24:09 -07:00
|
|
|
use plonky2::field::types::Field;
|
2022-06-25 13:34:04 -07:00
|
|
|
use plonky2::hash::hash_types::RichField;
|
|
|
|
|
use plonky2::iop::ext_target::ExtensionTarget;
|
2022-05-04 20:57:07 +02:00
|
|
|
use plonky2::util::transpose;
|
|
|
|
|
|
2022-06-25 13:34:04 -07:00
|
|
|
/// Construct an integer from its constituent bits (in little-endian order)
|
|
|
|
|
pub fn limb_from_bits_le<P: PackedField>(iter: impl IntoIterator<Item = P>) -> P {
|
|
|
|
|
// TODO: This is technically wrong, as 1 << i won't be canonical for all fields...
|
|
|
|
|
iter.into_iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.map(|(i, bit)| bit * P::Scalar::from_canonical_u64(1 << i))
|
|
|
|
|
.sum()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Construct an integer from its constituent bits (in little-endian order): recursive edition
|
|
|
|
|
pub fn limb_from_bits_le_recursive<F: RichField + Extendable<D>, const D: usize>(
|
|
|
|
|
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
|
|
|
|
|
iter: impl IntoIterator<Item = ExtensionTarget<D>>,
|
|
|
|
|
) -> ExtensionTarget<D> {
|
|
|
|
|
iter.into_iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.fold(builder.zero_extension(), |acc, (i, bit)| {
|
|
|
|
|
// TODO: This is technically wrong, as 1 << i won't be canonical for all fields...
|
|
|
|
|
builder.mul_const_add_extension(F::from_canonical_u64(1 << i), bit, acc)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-04 20:57:07 +02:00
|
|
|
/// A helper function to transpose a row-wise trace and put it in the format that `prove` expects.
|
|
|
|
|
pub fn trace_rows_to_poly_values<F: Field, const COLUMNS: usize>(
|
|
|
|
|
trace_rows: Vec<[F; COLUMNS]>,
|
|
|
|
|
) -> Vec<PolynomialValues<F>> {
|
|
|
|
|
let trace_row_vecs = trace_rows.into_iter().map(|row| row.to_vec()).collect_vec();
|
|
|
|
|
let trace_col_vecs: Vec<Vec<F>> = transpose(&trace_row_vecs);
|
|
|
|
|
trace_col_vecs
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|column| PolynomialValues::new(column))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
2022-08-25 12:24:22 -07:00
|
|
|
|
|
|
|
|
/// Returns the 32-bit little-endian limbs of a `U256`.
|
|
|
|
|
pub(crate) fn u256_limbs<F: Field>(u256: U256) -> [F; 8] {
|
|
|
|
|
u256.0
|
|
|
|
|
.into_iter()
|
|
|
|
|
.flat_map(|limb_64| {
|
2022-08-25 23:35:38 -07:00
|
|
|
let lo = limb_64 as u32;
|
2022-08-25 12:24:22 -07:00
|
|
|
let hi = (limb_64 >> 32) as u32;
|
|
|
|
|
[lo, hi]
|
|
|
|
|
})
|
|
|
|
|
.map(F::from_canonical_u32)
|
|
|
|
|
.collect_vec()
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-29 13:45:46 -06:00
|
|
|
/// Returns the 32-bit little-endian limbs of a `H256`.
|
|
|
|
|
pub(crate) fn h256_limbs<F: Field>(h256: H256) -> [F; 8] {
|
|
|
|
|
h256.0
|
|
|
|
|
.chunks(4)
|
|
|
|
|
.map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()))
|
|
|
|
|
.map(F::from_canonical_u32)
|
|
|
|
|
.collect_vec()
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-25 12:24:22 -07:00
|
|
|
/// Returns the 32-bit limbs of a `U160`.
|
|
|
|
|
pub(crate) fn h160_limbs<F: Field>(h160: H160) -> [F; 5] {
|
|
|
|
|
h160.0
|
|
|
|
|
.chunks(4)
|
|
|
|
|
.map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()))
|
|
|
|
|
.map(F::from_canonical_u32)
|
|
|
|
|
.collect_vec()
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap()
|
|
|
|
|
}
|
2022-08-29 18:10:51 -07:00
|
|
|
|
|
|
|
|
pub(crate) const fn indices_arr<const N: usize>() -> [usize; N] {
|
|
|
|
|
let mut indices_arr = [0; N];
|
|
|
|
|
let mut i = 0;
|
|
|
|
|
while i < N {
|
|
|
|
|
indices_arr[i] = i;
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
indices_arr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) unsafe fn transmute_no_compile_time_size_checks<T, U>(value: T) -> U {
|
|
|
|
|
debug_assert_eq!(size_of::<T>(), size_of::<U>());
|
|
|
|
|
// Need ManuallyDrop so that `value` is not dropped by this function.
|
|
|
|
|
let value = ManuallyDrop::new(value);
|
|
|
|
|
// Copy the bit pattern. The original value is no longer safe to use.
|
|
|
|
|
transmute_copy(&value)
|
|
|
|
|
}
|