use eth_types::{evm_types::OpcodeId, Field, U256};
use halo2_proofs::plonk::Expression;
pub mod sum {
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
pub fn expr<F: Field, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
inputs
.into_iter()
.fold(0.expr(), |acc, input| acc + input.expr())
}
pub fn value<F: Field>(values: &[u8]) -> F {
values
.iter()
.fold(F::ZERO, |acc, value| acc + F::from(*value as u64))
}
}
pub mod and {
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
pub fn expr<F: Field, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
inputs
.into_iter()
.fold(1.expr(), |acc, input| acc * input.expr())
}
pub fn value<F: Field>(inputs: Vec<F>) -> F {
inputs.iter().fold(F::ONE, |acc, input| acc * input)
}
}
pub mod or {
use super::{and, not};
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
pub fn expr<F: Field, E: Expr<F>, I: IntoIterator<Item = E>>(inputs: I) -> Expression<F> {
not::expr(and::expr(inputs.into_iter().map(not::expr)))
}
pub fn value<F: Field>(inputs: Vec<F>) -> F {
not::value(and::value(inputs.into_iter().map(not::value).collect()))
}
}
pub mod not {
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
pub fn expr<F: Field, E: Expr<F>>(b: E) -> Expression<F> {
1.expr() - b.expr()
}
pub fn value<F: Field>(b: F) -> F {
F::ONE - b
}
}
pub mod xor {
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
pub fn expr<F: Field, E: Expr<F>>(a: E, b: E) -> Expression<F> {
a.expr() + b.expr() - 2.expr() * a.expr() * b.expr()
}
pub fn value<F: Field>(a: F, b: F) -> F {
a + b - F::from(2u64) * a * b
}
}
pub mod select {
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
pub fn expr<F: Field>(
selector: Expression<F>,
when_true: Expression<F>,
when_false: Expression<F>,
) -> Expression<F> {
selector.clone() * when_true + (1.expr() - selector) * when_false
}
pub fn value<F: Field>(selector: F, when_true: F, when_false: F) -> F {
selector * when_true + (F::ONE - selector) * when_false
}
pub fn value_word<F: Field>(
selector: F,
when_true: [u8; 32],
when_false: [u8; 32],
) -> [u8; 32] {
if selector == F::ONE {
when_true
} else {
when_false
}
}
}
pub mod pow {
use crate::util::Expr;
use eth_types::Field;
use halo2_proofs::plonk::Expression;
use super::Scalar;
pub fn expr<F: Field>(value: Expression<F>, exponent: usize) -> Expression<F> {
let mut result = 1.expr();
for _ in 0..exponent {
result = result * value.expr();
}
result
}
pub fn value<F: Field>(value: F, exponent: usize) -> F {
let mut result = 1.scalar();
for _ in 0..exponent {
result *= value;
}
result
}
}
pub trait Scalar<F: Field> {
fn scalar(&self) -> F;
}
#[macro_export]
macro_rules! impl_scalar {
($type:ty) => {
impl<F: eth_types::Field> $crate::util::Scalar<F> for $type {
#[inline]
fn scalar(&self) -> F {
F::from(*self as u64)
}
}
};
($type:ty, $method:path) => {
impl<F: eth_types::Field> $crate::util::Scalar<F> for $type {
#[inline]
fn scalar(&self) -> F {
F::from($method(self) as u64)
}
}
};
}
pub trait Expr<F: Field> {
fn expr(&self) -> Expression<F>;
}
#[macro_export]
macro_rules! impl_expr {
($type:ty) => {
$crate::impl_scalar!($type);
impl<F: eth_types::Field> $crate::util::Expr<F> for $type {
#[inline]
fn expr(&self) -> Expression<F> {
Expression::Constant(F::from(*self as u64))
}
}
};
($type:ty, $method:path) => {
$crate::impl_scalar!($type, $method);
impl<F: eth_types::Field> $crate::util::Expr<F> for $type {
#[inline]
fn expr(&self) -> Expression<F> {
Expression::Constant(F::from($method(self) as u64))
}
}
};
}
impl_expr!(bool);
impl_expr!(u8);
impl_expr!(u64);
impl_expr!(usize);
impl_expr!(isize);
impl_expr!(OpcodeId, OpcodeId::as_u8);
impl<F: Field> Scalar<F> for i32 {
#[inline]
fn scalar(&self) -> F {
F::from(self.unsigned_abs() as u64) * if self.is_negative() { -F::ONE } else { F::ONE }
}
}
impl<F: Field> Scalar<F> for &F {
#[inline]
fn scalar(&self) -> F {
*(*self)
}
}
impl<F: Field> Expr<F> for i32 {
#[inline]
fn expr(&self) -> Expression<F> {
Expression::Constant(self.scalar())
}
}
impl<F: Field> Expr<F> for Expression<F> {
#[inline]
fn expr(&self) -> Expression<F> {
self.clone()
}
}
impl<F: Field> Expr<F> for &Expression<F> {
#[inline]
fn expr(&self) -> Expression<F> {
(*self).clone()
}
}
pub fn expr_from_bytes<F: Field, E: Expr<F>>(bytes: &[E]) -> Expression<F> {
let mut value = 0.expr();
let mut multiplier = F::ONE;
for byte in bytes.iter() {
value = value + byte.expr() * multiplier;
multiplier *= F::from(256);
}
value
}
pub fn pow_of_two<F: Field>(by: usize) -> F {
F::from(2).pow([by as u64, 0, 0, 0])
}
pub fn split_u256(value: &U256) -> (U256, U256) {
(
U256([value.0[0], value.0[1], 0, 0]),
U256([value.0[2], value.0[3], 0, 0]),
)
}
pub fn split_u256_limb64(value: &U256) -> [U256; 4] {
[
U256([value.0[0], 0, 0, 0]),
U256([value.0[1], 0, 0, 0]),
U256([value.0[2], 0, 0, 0]),
U256([value.0[3], 0, 0, 0]),
]
}