2022-11-30 22:00:57 -08:00
|
|
|
use ethereum_types::U256;
|
|
|
|
|
|
2022-12-27 18:42:34 -08:00
|
|
|
use crate::bn254::BN_BASE;
|
2022-11-30 22:00:57 -08:00
|
|
|
use crate::util::{addmod, mulmod, submod};
|
2022-11-30 15:25:07 -08:00
|
|
|
|
2022-06-29 11:56:48 +10:00
|
|
|
mod add;
|
2022-08-26 09:13:47 +10:00
|
|
|
mod compare;
|
2022-10-07 17:15:50 +11:00
|
|
|
mod modular;
|
2022-06-29 11:56:48 +10:00
|
|
|
mod mul;
|
|
|
|
|
mod sub;
|
|
|
|
|
mod utils;
|
|
|
|
|
|
|
|
|
|
pub mod arithmetic_stark;
|
|
|
|
|
pub(crate) mod columns;
|
2022-11-30 15:25:07 -08:00
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
|
|
|
pub(crate) enum BinaryOperator {
|
2022-11-30 17:45:31 -08:00
|
|
|
Add,
|
2022-11-30 15:25:07 -08:00
|
|
|
Mul,
|
|
|
|
|
Sub,
|
|
|
|
|
Div,
|
|
|
|
|
Mod,
|
|
|
|
|
Lt,
|
|
|
|
|
Gt,
|
|
|
|
|
Shl,
|
|
|
|
|
Shr,
|
2022-11-30 21:00:48 -08:00
|
|
|
AddFp254,
|
|
|
|
|
MulFp254,
|
|
|
|
|
SubFp254,
|
2022-11-30 15:25:07 -08:00
|
|
|
}
|
|
|
|
|
|
2022-11-30 18:12:31 -08:00
|
|
|
impl BinaryOperator {
|
|
|
|
|
pub(crate) fn result(&self, input0: U256, input1: U256) -> U256 {
|
|
|
|
|
match self {
|
2022-12-03 21:09:57 -08:00
|
|
|
BinaryOperator::Add => input0.overflowing_add(input1).0,
|
|
|
|
|
BinaryOperator::Mul => input0.overflowing_mul(input1).0,
|
|
|
|
|
BinaryOperator::Sub => input0.overflowing_sub(input1).0,
|
|
|
|
|
BinaryOperator::Div => {
|
|
|
|
|
if input1.is_zero() {
|
|
|
|
|
U256::zero()
|
|
|
|
|
} else {
|
|
|
|
|
input0 / input1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BinaryOperator::Mod => {
|
|
|
|
|
if input1.is_zero() {
|
|
|
|
|
U256::zero()
|
|
|
|
|
} else {
|
|
|
|
|
input0 % input1
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-30 18:12:31 -08:00
|
|
|
BinaryOperator::Lt => {
|
|
|
|
|
if input0 < input1 {
|
|
|
|
|
U256::one()
|
|
|
|
|
} else {
|
|
|
|
|
U256::zero()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BinaryOperator::Gt => {
|
|
|
|
|
if input0 > input1 {
|
|
|
|
|
U256::one()
|
|
|
|
|
} else {
|
|
|
|
|
U256::zero()
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-03 21:09:57 -08:00
|
|
|
BinaryOperator::Shl => {
|
|
|
|
|
if input0 > 255.into() {
|
|
|
|
|
U256::zero()
|
|
|
|
|
} else {
|
|
|
|
|
input1 << input0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BinaryOperator::Shr => {
|
|
|
|
|
if input0 > 255.into() {
|
|
|
|
|
U256::zero()
|
|
|
|
|
} else {
|
|
|
|
|
input1 >> input0
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-27 18:42:34 -08:00
|
|
|
BinaryOperator::AddFp254 => addmod(input0, input1, BN_BASE),
|
|
|
|
|
BinaryOperator::MulFp254 => mulmod(input0, input1, BN_BASE),
|
|
|
|
|
BinaryOperator::SubFp254 => submod(input0, input1, BN_BASE),
|
2022-11-30 18:12:31 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-30 15:25:07 -08:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
|
|
|
pub(crate) enum TernaryOperator {
|
|
|
|
|
AddMod,
|
|
|
|
|
MulMod,
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-30 18:12:31 -08:00
|
|
|
impl TernaryOperator {
|
|
|
|
|
pub(crate) fn result(&self, input0: U256, input1: U256, input2: U256) -> U256 {
|
|
|
|
|
match self {
|
2022-11-30 21:00:48 -08:00
|
|
|
TernaryOperator::AddMod => addmod(input0, input1, input2),
|
|
|
|
|
TernaryOperator::MulMod => mulmod(input0, input1, input2),
|
2022-11-30 18:12:31 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-30 15:25:07 -08:00
|
|
|
#[derive(Debug)]
|
2022-12-02 14:49:32 -08:00
|
|
|
#[allow(unused)] // TODO: Should be used soon.
|
2022-11-30 15:25:07 -08:00
|
|
|
pub(crate) enum Operation {
|
|
|
|
|
BinaryOperation {
|
|
|
|
|
operator: BinaryOperator,
|
|
|
|
|
input0: U256,
|
|
|
|
|
input1: U256,
|
|
|
|
|
result: U256,
|
|
|
|
|
},
|
|
|
|
|
TernaryOperation {
|
|
|
|
|
operator: TernaryOperator,
|
|
|
|
|
input0: U256,
|
|
|
|
|
input1: U256,
|
|
|
|
|
input2: U256,
|
|
|
|
|
result: U256,
|
|
|
|
|
},
|
|
|
|
|
}
|
2022-11-30 18:12:31 -08:00
|
|
|
|
|
|
|
|
impl Operation {
|
|
|
|
|
pub(crate) fn binary(operator: BinaryOperator, input0: U256, input1: U256) -> Self {
|
|
|
|
|
let result = operator.result(input0, input1);
|
|
|
|
|
Self::BinaryOperation {
|
|
|
|
|
operator,
|
|
|
|
|
input0,
|
|
|
|
|
input1,
|
|
|
|
|
result,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn ternary(
|
|
|
|
|
operator: TernaryOperator,
|
|
|
|
|
input0: U256,
|
|
|
|
|
input1: U256,
|
|
|
|
|
input2: U256,
|
|
|
|
|
) -> Self {
|
|
|
|
|
let result = operator.result(input0, input1, input2);
|
|
|
|
|
Self::TernaryOperation {
|
|
|
|
|
operator,
|
|
|
|
|
input0,
|
|
|
|
|
input1,
|
|
|
|
|
input2,
|
|
|
|
|
result,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn result(&self) -> U256 {
|
|
|
|
|
match self {
|
|
|
|
|
Operation::BinaryOperation { result, .. } => *result,
|
|
|
|
|
Operation::TernaryOperation { result, .. } => *result,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|