1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
use crate::{
interpreters::keccak::interpreter::Interpreter,
lookups::{Lookup, LookupTableIDs::*},
};
use ark_ff::{One, Zero};
use std::fmt::Debug;
/// This trait contains helper functions for the lookups used in the Keccak circuit
/// using the zkVM lookup tables
pub trait LogupHelpers<F: One + Debug + Zero>
where
Self: Interpreter<F>,
{
/// Adds a lookup to the RangeCheck16 table
fn lookup_rc16(&mut self, flag: Self::Variable, value: Self::Variable) {
self.add_lookup(flag, Lookup::read_one(RangeCheck16Lookup, vec![value]));
}
/// Adds a lookup to the Reset table
fn lookup_reset(
&mut self,
flag: Self::Variable,
dense: Self::Variable,
sparse: Self::Variable,
) {
self.add_lookup(flag, Lookup::read_one(ResetLookup, vec![dense, sparse]));
}
/// Adds a lookup to the Shift table
fn lookup_sparse(&mut self, flag: Self::Variable, value: Self::Variable) {
self.add_lookup(flag, Lookup::read_one(SparseLookup, vec![value]));
}
/// Adds a lookup to the Byte table
fn lookup_byte(&mut self, flag: Self::Variable, value: Self::Variable) {
self.add_lookup(flag, Lookup::read_one(ByteLookup, vec![value]));
}
/// Adds a lookup to the Pad table
fn lookup_pad(&mut self, flag: Self::Variable, value: Vec<Self::Variable>) {
self.add_lookup(flag, Lookup::read_one(PadLookup, value));
}
/// Adds a lookup to the RoundConstants table
fn lookup_round_constants(&mut self, flag: Self::Variable, value: Vec<Self::Variable>) {
self.add_lookup(flag, Lookup::read_one(RoundConstantsLookup, value));
}
fn read_syscall(&mut self, flag: Self::Variable, value: Vec<Self::Variable>) {
self.add_lookup(flag, Lookup::read_one(SyscallLookup, value));
}
fn write_syscall(&mut self, flag: Self::Variable, value: Vec<Self::Variable>) {
self.add_lookup(flag, Lookup::write_one(SyscallLookup, value));
}
}
/// This trait contains helper functions for boolean operations used in the Keccak circuit
pub trait BoolHelpers<F: One + Debug + Zero>
where
Self: Interpreter<F>,
{
/// Degree-2 variable encoding whether the input is a boolean value (0 = yes)
fn is_boolean(x: Self::Variable) -> Self::Variable {
x.clone() * (x - Self::Variable::one())
}
/// Degree-1 variable encoding the negation of the input
/// Note: it only works as expected if the input is a boolean value
fn not(x: Self::Variable) -> Self::Variable {
Self::Variable::one() - x
}
/// Degree-1 variable encoding whether the input is the value one (0 = yes)
fn is_one(x: Self::Variable) -> Self::Variable {
Self::not(x)
}
/// Degree-2 variable encoding whether the first input is nonzero (0 = yes).
/// It requires the second input to be the multiplicative inverse of the first.
/// Note: if the first input is zero, there is no multiplicative inverse.
fn is_nonzero(x: Self::Variable, x_inv: Self::Variable) -> Self::Variable {
Self::is_one(x * x_inv)
}
// The following two degree-2 constraints define the is_zero function meaning (1 = yes):
// - if x = 0 then is_zero(x) = 1
// - if x ≠ 0 then is_zero(x) = 0
// It is obtained by combining these two equations:
// x * xinv = 1 - z
// x * z = 0
// When x = 0, xinv could be anything, like 1.
fn is_zero(
x: Self::Variable,
x_inv: Self::Variable,
z: Self::Variable,
) -> (Self::Variable, Self::Variable) {
(
x.clone() * x_inv.clone() - z.clone() + Self::Variable::one(),
x * z,
)
}
/// Degree-2 variable encoding the XOR of two variables which should be boolean (1 = true)
fn xor(x: Self::Variable, y: Self::Variable) -> Self::Variable {
x.clone() + y.clone() - Self::constant(2) * x * y
}
/// Degree-2 variable encoding the OR of two variables, which should be boolean (1 = true)
fn or(x: Self::Variable, y: Self::Variable) -> Self::Variable {
x.clone() + y.clone() - x * y
}
/// Degree-2 variable encoding whether at least one of the two inputs is zero (0 = yes)
fn either_zero(x: Self::Variable, y: Self::Variable) -> Self::Variable {
x * y
}
}
/// This trait contains helper functions for arithmetic operations used in the Keccak circuit
pub trait ArithHelpers<F: One + Debug + Zero>
where
Self: Interpreter<F>,
{
/// Returns a variable representing the value zero
fn zero() -> Self::Variable {
Self::constant(0)
}
/// Returns a variable representing the value one
fn one() -> Self::Variable {
Self::constant(1)
}
/// Returns a variable representing the value two
fn two() -> Self::Variable {
Self::constant(2)
}
/// Returns a variable representing the value 2^x
fn two_pow(x: u64) -> Self::Variable;
}