mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-05 20:10:32 +00:00
Add MessageSchedule gates and assign fixed column cells
This commit is contained in:
parent
fc4f3576a0
commit
88379fa62f
5 changed files with 804 additions and 7 deletions
|
|
@ -7,10 +7,12 @@ use crate::{
|
||||||
plonk::{Advice, Column, ConstraintSystem, Error, Permutation},
|
plonk::{Advice, Column, ConstraintSystem, Error, Permutation},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod gates;
|
||||||
mod message_schedule;
|
mod message_schedule;
|
||||||
mod spread_table;
|
mod spread_table;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
use gates::*;
|
||||||
use message_schedule::*;
|
use message_schedule::*;
|
||||||
use spread_table::*;
|
use spread_table::*;
|
||||||
|
|
||||||
|
|
|
||||||
118
src/gadget/sha256/table16/gates.rs
Normal file
118
src/gadget/sha256/table16/gates.rs
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
use crate::arithmetic::FieldExt;
|
||||||
|
use crate::plonk::Expression;
|
||||||
|
|
||||||
|
pub struct Gate<F: FieldExt>(pub Expression<F>);
|
||||||
|
|
||||||
|
impl<F: FieldExt> Gate<F> {
|
||||||
|
fn ones() -> Expression<F> {
|
||||||
|
Expression::Constant(F::one())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper gates
|
||||||
|
fn lagrange_interpolate(
|
||||||
|
var: Expression<F>,
|
||||||
|
points: Vec<u16>,
|
||||||
|
evals: Vec<u32>,
|
||||||
|
) -> (F, Expression<F>) {
|
||||||
|
assert_eq!(points.len(), evals.len());
|
||||||
|
let deg = points.len();
|
||||||
|
|
||||||
|
fn factorial(n: u64) -> u64 {
|
||||||
|
if n < 2 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
n * factorial(n - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale the whole expression by factor to avoid divisions
|
||||||
|
let factor = factorial((deg - 1) as u64);
|
||||||
|
|
||||||
|
let numerator = |var: Expression<F>, eval: u32, idx: u64| {
|
||||||
|
let mut expr = Self::ones();
|
||||||
|
for i in 0..deg {
|
||||||
|
let i = i as u64;
|
||||||
|
if i != idx {
|
||||||
|
expr = expr * (Self::ones() * (-F::one()) * F::from_u64(i) + var.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr * F::from_u64(eval.into())
|
||||||
|
};
|
||||||
|
let denominator = |idx: i32| {
|
||||||
|
let mut denom: i32 = 1;
|
||||||
|
for i in 0..deg {
|
||||||
|
let i = i as i32;
|
||||||
|
if i != idx {
|
||||||
|
denom *= idx - i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if denom < 0 {
|
||||||
|
-F::one() * F::from_u64(factor / (-denom as u64))
|
||||||
|
} else {
|
||||||
|
F::from_u64(factor / (denom as u64))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut expr = Self::ones() * F::zero();
|
||||||
|
for ((idx, _), eval) in points.iter().enumerate().zip(evals.iter()) {
|
||||||
|
expr = expr + numerator(var.clone(), *eval, idx as u64) * denominator(idx as i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
(F::from_u64(factor), expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn range_check(value: Expression<F>, lower_range: u64, upper_range: u64) -> Expression<F> {
|
||||||
|
let mut expr = Self::ones();
|
||||||
|
for i in lower_range..(upper_range + 1) {
|
||||||
|
expr = expr * (Self::ones() * (-F::one()) * F::from_u64(i) + value.clone())
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2-bit range check
|
||||||
|
fn two_bit_range_check(value: Expression<F>) -> Expression<F> {
|
||||||
|
Self::range_check(value, 0, (1 << 2) - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2-bit spread interpolation
|
||||||
|
fn two_bit_spread(dense: Expression<F>, spread: Expression<F>) -> Expression<F> {
|
||||||
|
let (factor, lagrange_poly) = Self::lagrange_interpolate(
|
||||||
|
dense,
|
||||||
|
vec![0b00, 0b01, 0b10, 0b11],
|
||||||
|
vec![0b0000, 0b0001, 0b0100, 0b0101],
|
||||||
|
);
|
||||||
|
|
||||||
|
lagrange_poly + (spread * factor * (-F::one()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3-bit range check
|
||||||
|
fn three_bit_range_check(value: Expression<F>) -> Expression<F> {
|
||||||
|
Self::range_check(value, 0, (1 << 3) - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3-bit spread
|
||||||
|
fn three_bit_spread(dense: Expression<F>, spread: Expression<F>) -> Expression<F> {
|
||||||
|
let (factor, lagrange_poly) = Self::lagrange_interpolate(
|
||||||
|
dense,
|
||||||
|
vec![0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111],
|
||||||
|
vec![
|
||||||
|
0b000000, 0b000001, 0b000100, 0b000101, 0b010000, 0b010001, 0b010100, 0b010101,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
lagrange_poly + (spread * factor * (-F::one()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spread and range check on 2-bit word
|
||||||
|
pub fn two_bit_spread_and_range(dense: Expression<F>, spread: Expression<F>) -> Expression<F> {
|
||||||
|
Self::two_bit_range_check(dense.clone()) + Self::two_bit_spread(dense, spread)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spread and range check on 3-bit word
|
||||||
|
pub fn three_bit_spread_and_range(
|
||||||
|
dense: Expression<F>,
|
||||||
|
spread: Expression<F>,
|
||||||
|
) -> Expression<F> {
|
||||||
|
Self::three_bit_range_check(dense.clone()) + Self::three_bit_spread(dense, spread)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,15 +7,17 @@ use crate::{
|
||||||
arithmetic::FieldExt,
|
arithmetic::FieldExt,
|
||||||
circuit::{Cell, Layouter},
|
circuit::{Cell, Layouter},
|
||||||
plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Permutation},
|
plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Permutation},
|
||||||
|
poly::Rotation,
|
||||||
};
|
};
|
||||||
|
|
||||||
// mod schedule_gates;
|
mod schedule_gates;
|
||||||
mod schedule_util;
|
mod schedule_util;
|
||||||
// mod subregion1;
|
// mod subregion1;
|
||||||
// mod subregion2;
|
// mod subregion2;
|
||||||
// mod subregion3;
|
// mod subregion3;
|
||||||
|
|
||||||
// use schedule_gates::ScheduleGate;
|
use schedule_gates::ScheduleGate;
|
||||||
|
use schedule_util::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(super) struct MessageWord {
|
pub(super) struct MessageWord {
|
||||||
|
|
@ -78,7 +80,208 @@ impl MessageSchedule {
|
||||||
let s_lower_sigma_0_v2 = meta.fixed_column();
|
let s_lower_sigma_0_v2 = meta.fixed_column();
|
||||||
let s_lower_sigma_1_v2 = meta.fixed_column();
|
let s_lower_sigma_1_v2 = meta.fixed_column();
|
||||||
|
|
||||||
// TODO: Create gates
|
// Rename these here for ease of matching the gates to the specification.
|
||||||
|
let a_0 = lookup.tag;
|
||||||
|
let a_1 = lookup.dense;
|
||||||
|
let a_2 = lookup.spread;
|
||||||
|
let a_3 = extras[0];
|
||||||
|
let a_4 = extras[1];
|
||||||
|
let a_5 = message_schedule;
|
||||||
|
let a_6 = extras[2];
|
||||||
|
let a_7 = extras[3];
|
||||||
|
let a_8 = extras[4];
|
||||||
|
let a_9 = extras[5];
|
||||||
|
|
||||||
|
// s_word for W_[16..64]
|
||||||
|
meta.create_gate("s_word for W_[16..64]", |meta| {
|
||||||
|
let s_word = meta.query_fixed(s_word, Rotation::cur());
|
||||||
|
|
||||||
|
let sigma_0_lo = meta.query_advice(a_6, Rotation::prev());
|
||||||
|
let sigma_0_hi = meta.query_advice(a_6, Rotation::cur());
|
||||||
|
|
||||||
|
let sigma_1_lo = meta.query_advice(a_7, Rotation::prev());
|
||||||
|
let sigma_1_hi = meta.query_advice(a_7, Rotation::cur());
|
||||||
|
|
||||||
|
let w_minus_9_lo = meta.query_advice(a_8, Rotation::prev());
|
||||||
|
let w_minus_9_hi = meta.query_advice(a_8, Rotation::cur());
|
||||||
|
|
||||||
|
let w_minus_16_lo = meta.query_advice(a_3, Rotation::prev());
|
||||||
|
let w_minus_16_hi = meta.query_advice(a_4, Rotation::prev());
|
||||||
|
|
||||||
|
let word = meta.query_advice(a_5, Rotation::cur());
|
||||||
|
let carry = meta.query_advice(a_9, Rotation::cur());
|
||||||
|
|
||||||
|
ScheduleGate::s_word(
|
||||||
|
s_word,
|
||||||
|
sigma_0_lo,
|
||||||
|
sigma_0_hi,
|
||||||
|
sigma_1_lo,
|
||||||
|
sigma_1_hi,
|
||||||
|
w_minus_9_lo,
|
||||||
|
w_minus_9_hi,
|
||||||
|
w_minus_16_lo,
|
||||||
|
w_minus_16_hi,
|
||||||
|
word,
|
||||||
|
carry,
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
});
|
||||||
|
|
||||||
|
// s_decompose_0 for all words
|
||||||
|
meta.create_gate("s_decompose_0", |meta| {
|
||||||
|
let s_decompose_0 = meta.query_fixed(s_decompose_0, Rotation::cur());
|
||||||
|
let lo = meta.query_advice(a_3, Rotation::cur());
|
||||||
|
let hi = meta.query_advice(a_4, Rotation::cur());
|
||||||
|
let word = meta.query_advice(a_5, Rotation::cur());
|
||||||
|
|
||||||
|
ScheduleGate::s_decompose_0(s_decompose_0, lo, hi, word).0
|
||||||
|
});
|
||||||
|
|
||||||
|
// s_decompose_1 for W_[1..14]
|
||||||
|
// (3, 4, 11, 14)-bit chunks
|
||||||
|
meta.create_gate("s_decompose_1", |meta| {
|
||||||
|
let s_decompose_1 = meta.query_fixed(s_decompose_1, Rotation::cur());
|
||||||
|
let a = meta.query_advice(a_3, Rotation::next()); // 3-bit chunk
|
||||||
|
let b = meta.query_advice(a_4, Rotation::next()); // 4-bit chunk
|
||||||
|
let c = meta.query_advice(a_1, Rotation::next()); // 11-bit chunk
|
||||||
|
let tag_c = meta.query_advice(a_0, Rotation::next());
|
||||||
|
let d = meta.query_advice(a_1, Rotation::cur()); // 14-bit chunk
|
||||||
|
let tag_d = meta.query_advice(a_0, Rotation::cur());
|
||||||
|
let word = meta.query_advice(a_5, Rotation::cur());
|
||||||
|
|
||||||
|
ScheduleGate::s_decompose_1(s_decompose_1, a, b, c, tag_c, d, tag_d, word).0
|
||||||
|
});
|
||||||
|
|
||||||
|
// s_decompose_2 for W_[14..49]
|
||||||
|
// (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||||
|
meta.create_gate("s_decompose_2", |meta| {
|
||||||
|
let s_decompose_2 = meta.query_fixed(s_decompose_2, Rotation::cur());
|
||||||
|
let a = meta.query_advice(a_3, Rotation::prev()); // 3-bit chunk
|
||||||
|
let b = meta.query_advice(a_1, Rotation::next()); // 4-bit chunk
|
||||||
|
let c = meta.query_advice(a_4, Rotation::prev()); // 3-bit chunk
|
||||||
|
let d = meta.query_advice(a_1, Rotation::cur()); // 7-bit chunk
|
||||||
|
let tag_d = meta.query_advice(a_0, Rotation::cur());
|
||||||
|
let e = meta.query_advice(a_3, Rotation::next()); // 1-bit chunk
|
||||||
|
let f = meta.query_advice(a_4, Rotation::next()); // 1-bit chunk
|
||||||
|
let g = meta.query_advice(a_1, Rotation::prev()); // 13-bit chunk
|
||||||
|
let tag_g = meta.query_advice(a_0, Rotation::prev());
|
||||||
|
let word = meta.query_advice(a_5, Rotation::cur());
|
||||||
|
|
||||||
|
ScheduleGate::s_decompose_2(s_decompose_2, a, b, c, d, tag_d, e, f, g, tag_g, word).0
|
||||||
|
});
|
||||||
|
|
||||||
|
// s_decompose_3 for W_49 to W_61
|
||||||
|
// (10, 7, 2, 13)-bit chunks
|
||||||
|
meta.create_gate("s_decompose_3", |meta| {
|
||||||
|
let s_decompose_3 = meta.query_fixed(s_decompose_3, Rotation::cur());
|
||||||
|
let a = meta.query_advice(a_1, Rotation::next()); // 10-bit chunk
|
||||||
|
let tag_a = meta.query_advice(a_0, Rotation::next());
|
||||||
|
let b = meta.query_advice(a_4, Rotation::next()); // 7-bit chunk
|
||||||
|
let c = meta.query_advice(a_3, Rotation::next()); // 2-bit chunk
|
||||||
|
let d = meta.query_advice(a_1, Rotation::cur()); // 13-bit chunk
|
||||||
|
let tag_d = meta.query_advice(a_0, Rotation::cur());
|
||||||
|
let word = meta.query_advice(a_5, Rotation::cur());
|
||||||
|
|
||||||
|
ScheduleGate::s_decompose_3(s_decompose_3, a, tag_a, b, c, d, tag_d, word).0
|
||||||
|
});
|
||||||
|
|
||||||
|
// sigma_0 v1 on W_[1..14]
|
||||||
|
// (3, 4, 11, 14)-bit chunks
|
||||||
|
meta.create_gate("sigma_0 v1", |meta| {
|
||||||
|
ScheduleGate::s_lower_sigma_0(
|
||||||
|
meta.query_fixed(s_lower_sigma_0, Rotation::cur()), // s_lower_sigma_0
|
||||||
|
meta.query_advice(a_2, Rotation::prev()), // spread_r0_even
|
||||||
|
meta.query_advice(a_2, Rotation::cur()), // spread_r0_odd
|
||||||
|
meta.query_advice(a_2, Rotation::next()), // spread_r1_even
|
||||||
|
meta.query_advice(a_3, Rotation::cur()), // spread_r1_odd
|
||||||
|
meta.query_advice(a_5, Rotation::next()), // a
|
||||||
|
meta.query_advice(a_6, Rotation::next()), // spread_a
|
||||||
|
meta.query_advice(a_6, Rotation::cur()), // b
|
||||||
|
meta.query_advice(a_3, Rotation::prev()), // b_lo
|
||||||
|
meta.query_advice(a_4, Rotation::prev()), // spread_b_lo
|
||||||
|
meta.query_advice(a_5, Rotation::prev()), // b_hi
|
||||||
|
meta.query_advice(a_6, Rotation::prev()), // spread_b_hi
|
||||||
|
meta.query_advice(a_4, Rotation::cur()), // spread_c
|
||||||
|
meta.query_advice(a_5, Rotation::cur()), // spread_d
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
});
|
||||||
|
|
||||||
|
// sigma_0 v2 on W_[14..49]
|
||||||
|
// (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||||
|
meta.create_gate("sigma_0 v2", |meta| {
|
||||||
|
ScheduleGate::s_lower_sigma_0_v2(
|
||||||
|
meta.query_fixed(s_lower_sigma_0_v2, Rotation::cur()), // s_lower_sigma_0_v2
|
||||||
|
meta.query_advice(a_2, Rotation::prev()), // spread_r0_even
|
||||||
|
meta.query_advice(a_2, Rotation::cur()), // spread_r0_odd
|
||||||
|
meta.query_advice(a_2, Rotation::next()), // spread_r1_even
|
||||||
|
meta.query_advice(a_3, Rotation::cur()), // spread_r1_odd
|
||||||
|
meta.query_advice(a_3, Rotation::next()), // a
|
||||||
|
meta.query_advice(a_4, Rotation::next()), // spread_a
|
||||||
|
meta.query_advice(a_6, Rotation::cur()), // b
|
||||||
|
meta.query_advice(a_3, Rotation::prev()), // b_lo
|
||||||
|
meta.query_advice(a_4, Rotation::prev()), // spread_b_lo
|
||||||
|
meta.query_advice(a_5, Rotation::prev()), // b_hi
|
||||||
|
meta.query_advice(a_6, Rotation::prev()), // spread_b_hi
|
||||||
|
meta.query_advice(a_5, Rotation::next()), // c
|
||||||
|
meta.query_advice(a_6, Rotation::next()), // spread_c
|
||||||
|
meta.query_advice(a_4, Rotation::cur()), // spread_d
|
||||||
|
meta.query_advice(a_7, Rotation::cur()), // spread_e
|
||||||
|
meta.query_advice(a_7, Rotation::next()), // spread_f
|
||||||
|
meta.query_advice(a_5, Rotation::cur()), // spread_g
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
});
|
||||||
|
|
||||||
|
// sigma_1 v2 on W_14 to W_48
|
||||||
|
// (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||||
|
meta.create_gate("sigma_1 v2", |meta| {
|
||||||
|
ScheduleGate::s_lower_sigma_1_v2(
|
||||||
|
meta.query_fixed(s_lower_sigma_1_v2, Rotation::cur()), // s_lower_sigma_1_v2
|
||||||
|
meta.query_advice(a_2, Rotation::prev()), // spread_r0_even
|
||||||
|
meta.query_advice(a_2, Rotation::cur()), // spread_r0_odd
|
||||||
|
meta.query_advice(a_2, Rotation::next()), // spread_r1_even
|
||||||
|
meta.query_advice(a_3, Rotation::cur()), // spread_r1_odd
|
||||||
|
meta.query_advice(a_3, Rotation::next()), // a
|
||||||
|
meta.query_advice(a_4, Rotation::next()), // spread_a
|
||||||
|
meta.query_advice(a_6, Rotation::cur()), // b
|
||||||
|
meta.query_advice(a_3, Rotation::prev()), // b_lo
|
||||||
|
meta.query_advice(a_4, Rotation::prev()), // spread_b_lo
|
||||||
|
meta.query_advice(a_5, Rotation::prev()), // b_hi
|
||||||
|
meta.query_advice(a_6, Rotation::prev()), // spread_b_hi
|
||||||
|
meta.query_advice(a_5, Rotation::next()), // c
|
||||||
|
meta.query_advice(a_6, Rotation::next()), // spread_c
|
||||||
|
meta.query_advice(a_4, Rotation::cur()), // spread_d
|
||||||
|
meta.query_advice(a_7, Rotation::cur()), // spread_e
|
||||||
|
meta.query_advice(a_7, Rotation::next()), // spread_f
|
||||||
|
meta.query_advice(a_5, Rotation::cur()), // spread_g
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
});
|
||||||
|
|
||||||
|
// sigma_1 v1 on W_49 to W_61
|
||||||
|
// (10, 7, 2, 13)-bit chunks
|
||||||
|
meta.create_gate("sigma_1 v1", |meta| {
|
||||||
|
ScheduleGate::s_lower_sigma_1(
|
||||||
|
meta.query_fixed(s_lower_sigma_1, Rotation::cur()), // s_lower_sigma_1
|
||||||
|
meta.query_advice(a_2, Rotation::prev()), // spread_r0_even
|
||||||
|
meta.query_advice(a_2, Rotation::cur()), // spread_r0_odd
|
||||||
|
meta.query_advice(a_2, Rotation::next()), // spread_r1_even
|
||||||
|
meta.query_advice(a_3, Rotation::cur()), // spread_r1_odd
|
||||||
|
meta.query_advice(a_4, Rotation::cur()), // spread_a
|
||||||
|
meta.query_advice(a_6, Rotation::cur()), // b
|
||||||
|
meta.query_advice(a_3, Rotation::prev()), // b_lo
|
||||||
|
meta.query_advice(a_4, Rotation::prev()), // spread_b_lo
|
||||||
|
meta.query_advice(a_5, Rotation::prev()), // b_mid
|
||||||
|
meta.query_advice(a_6, Rotation::prev()), // spread_b_mid
|
||||||
|
meta.query_advice(a_5, Rotation::next()), // b_hi
|
||||||
|
meta.query_advice(a_6, Rotation::next()), // spread_b_hi
|
||||||
|
meta.query_advice(a_3, Rotation::next()), // c
|
||||||
|
meta.query_advice(a_4, Rotation::next()), // spread_c
|
||||||
|
meta.query_advice(a_5, Rotation::cur()), // spread_d
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
});
|
||||||
|
|
||||||
MessageSchedule {
|
MessageSchedule {
|
||||||
lookup,
|
lookup,
|
||||||
|
|
@ -107,10 +310,92 @@ impl MessageSchedule {
|
||||||
|
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|| "process message block",
|
|| "process message block",
|
||||||
|region| {
|
|mut region| {
|
||||||
let region = std::cell::RefCell::new(region);
|
w = Vec::<MessageWord>::with_capacity(ROUNDS);
|
||||||
|
w_halves = Vec::<(CellValue16, CellValue16)>::with_capacity(ROUNDS);
|
||||||
|
|
||||||
// TODO: Assign cells
|
// Assign all fixed columns
|
||||||
|
for index in 1..14 {
|
||||||
|
let row = get_word_row(index);
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_decompose_1",
|
||||||
|
self.s_decompose_1,
|
||||||
|
row,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_lower_sigma_0",
|
||||||
|
self.s_lower_sigma_0,
|
||||||
|
row + 3,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for index in 14..49 {
|
||||||
|
let row = get_word_row(index);
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_decompose_2",
|
||||||
|
self.s_decompose_2,
|
||||||
|
row,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_lower_sigma_0_v2",
|
||||||
|
self.s_lower_sigma_0_v2,
|
||||||
|
row + 3,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_lower_sigma_1_v2",
|
||||||
|
self.s_lower_sigma_1_v2,
|
||||||
|
row + SIGMA_0_V2_ROWS + 3,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let new_word_idx = index + 2;
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_word",
|
||||||
|
self.s_word,
|
||||||
|
get_word_row(new_word_idx - 16) + 1,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for index in 49..62 {
|
||||||
|
let row = get_word_row(index);
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_decompose_3",
|
||||||
|
self.s_decompose_3,
|
||||||
|
row,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_lower_sigma_1",
|
||||||
|
self.s_lower_sigma_1,
|
||||||
|
row + 3,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let new_word_idx = index + 2;
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_word",
|
||||||
|
self.s_word,
|
||||||
|
get_word_row(new_word_idx - 16) + 1,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for index in 0..64 {
|
||||||
|
let row = get_word_row(index);
|
||||||
|
region.assign_fixed(
|
||||||
|
|| "s_decompose_0",
|
||||||
|
self.s_decompose_0,
|
||||||
|
row,
|
||||||
|
|| Ok(F::one()),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Assign advice columns
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
|
@ -118,4 +403,40 @@ impl MessageSchedule {
|
||||||
|
|
||||||
Ok((w.try_into().unwrap(), w_halves.try_into().unwrap()))
|
Ok((w.try_into().unwrap(), w_halves.try_into().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Empty configuration without gates. Useful for fast testing
|
||||||
|
pub(super) fn empty_configure<F: FieldExt>(
|
||||||
|
meta: &mut ConstraintSystem<F>,
|
||||||
|
lookup: SpreadInputs,
|
||||||
|
message_schedule: Column<Advice>,
|
||||||
|
extras: [Column<Advice>; 6],
|
||||||
|
perm: Permutation,
|
||||||
|
) -> Self {
|
||||||
|
// Create fixed columns for the selectors we will require.
|
||||||
|
let s_word = meta.fixed_column();
|
||||||
|
let s_decompose_0 = meta.fixed_column();
|
||||||
|
let s_decompose_1 = meta.fixed_column();
|
||||||
|
let s_decompose_2 = meta.fixed_column();
|
||||||
|
let s_decompose_3 = meta.fixed_column();
|
||||||
|
let s_lower_sigma_0 = meta.fixed_column();
|
||||||
|
let s_lower_sigma_1 = meta.fixed_column();
|
||||||
|
let s_lower_sigma_0_v2 = meta.fixed_column();
|
||||||
|
let s_lower_sigma_1_v2 = meta.fixed_column();
|
||||||
|
|
||||||
|
MessageSchedule {
|
||||||
|
lookup,
|
||||||
|
message_schedule,
|
||||||
|
extras,
|
||||||
|
s_word,
|
||||||
|
s_decompose_0,
|
||||||
|
s_decompose_1,
|
||||||
|
s_decompose_2,
|
||||||
|
s_decompose_3,
|
||||||
|
s_lower_sigma_0,
|
||||||
|
s_lower_sigma_1,
|
||||||
|
s_lower_sigma_0_v2,
|
||||||
|
s_lower_sigma_1_v2,
|
||||||
|
perm,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
356
src/gadget/sha256/table16/message_schedule/schedule_gates.rs
Normal file
356
src/gadget/sha256/table16/message_schedule/schedule_gates.rs
Normal file
|
|
@ -0,0 +1,356 @@
|
||||||
|
use super::super::Gate;
|
||||||
|
use crate::arithmetic::FieldExt;
|
||||||
|
use crate::plonk::Expression;
|
||||||
|
|
||||||
|
pub struct ScheduleGate<F: FieldExt>(pub Expression<F>);
|
||||||
|
|
||||||
|
impl<F: FieldExt> ScheduleGate<F> {
|
||||||
|
/// s_word for W_16 to W_63
|
||||||
|
pub fn s_word(
|
||||||
|
s_word: Expression<F>,
|
||||||
|
sigma_0_lo: Expression<F>,
|
||||||
|
sigma_0_hi: Expression<F>,
|
||||||
|
sigma_1_lo: Expression<F>,
|
||||||
|
sigma_1_hi: Expression<F>,
|
||||||
|
w_minus_9_lo: Expression<F>,
|
||||||
|
w_minus_9_hi: Expression<F>,
|
||||||
|
w_minus_16_lo: Expression<F>,
|
||||||
|
w_minus_16_hi: Expression<F>,
|
||||||
|
word: Expression<F>,
|
||||||
|
carry: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let lo = sigma_0_lo + sigma_1_lo + w_minus_9_lo + w_minus_16_lo;
|
||||||
|
let hi = sigma_0_hi + sigma_1_hi + w_minus_9_hi + w_minus_16_hi;
|
||||||
|
|
||||||
|
let word_check = lo
|
||||||
|
+ hi * F::from_u64(1 << 16)
|
||||||
|
+ (carry.clone() * F::from_u64(1 << 32) * (-F::one()))
|
||||||
|
+ (word * (-F::one()));
|
||||||
|
let carry_check = Gate::range_check(carry, 0, 3);
|
||||||
|
|
||||||
|
ScheduleGate(s_word * (word_check + carry_check))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// s_decompose_0 for all words
|
||||||
|
pub fn s_decompose_0(
|
||||||
|
s_decompose_0: Expression<F>,
|
||||||
|
lo: Expression<F>,
|
||||||
|
hi: Expression<F>,
|
||||||
|
word: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
ScheduleGate(s_decompose_0 * (lo + hi * F::from_u64(1 << 16) + word * (-F::one())))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// s_decompose_1 for W_1 to W_13
|
||||||
|
/// (3, 4, 11, 14)-bit chunks
|
||||||
|
pub fn s_decompose_1(
|
||||||
|
s_decompose_1: Expression<F>,
|
||||||
|
a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
c: Expression<F>,
|
||||||
|
tag_c: Expression<F>,
|
||||||
|
d: Expression<F>,
|
||||||
|
tag_d: Expression<F>,
|
||||||
|
word: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let decompose_check = a
|
||||||
|
+ b * F::from_u64(1 << 3)
|
||||||
|
+ c * F::from_u64(1 << 7)
|
||||||
|
+ d * F::from_u64(1 << 18)
|
||||||
|
+ word * (-F::one());
|
||||||
|
let range_check_tag_c = Gate::range_check(tag_c, 0, 2);
|
||||||
|
let range_check_tag_d = Gate::range_check(tag_d, 0, 4);
|
||||||
|
ScheduleGate(s_decompose_1 * (decompose_check + range_check_tag_c + range_check_tag_d))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// s_decompose_2 for W_14 to W_48
|
||||||
|
/// (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||||
|
pub fn s_decompose_2(
|
||||||
|
s_decompose_2: Expression<F>,
|
||||||
|
a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
c: Expression<F>,
|
||||||
|
d: Expression<F>,
|
||||||
|
tag_d: Expression<F>,
|
||||||
|
e: Expression<F>,
|
||||||
|
f: Expression<F>,
|
||||||
|
g: Expression<F>,
|
||||||
|
tag_g: Expression<F>,
|
||||||
|
word: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let decompose_check = a
|
||||||
|
+ b * F::from_u64(1 << 3)
|
||||||
|
+ c * F::from_u64(1 << 7)
|
||||||
|
+ d * F::from_u64(1 << 10)
|
||||||
|
+ e * F::from_u64(1 << 17)
|
||||||
|
+ f * F::from_u64(1 << 18)
|
||||||
|
+ g * F::from_u64(1 << 19)
|
||||||
|
+ word * (-F::one());
|
||||||
|
let range_check_tag_d = Gate::range_check(tag_d, 0, 0);
|
||||||
|
let range_check_tag_g = Gate::range_check(tag_g, 0, 3);
|
||||||
|
ScheduleGate(s_decompose_2 * (decompose_check + range_check_tag_g + range_check_tag_d))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// s_decompose_3 for W_49 to W_61
|
||||||
|
/// (10, 7, 2, 13)-bit chunks
|
||||||
|
pub fn s_decompose_3(
|
||||||
|
s_decompose_3: Expression<F>,
|
||||||
|
a: Expression<F>,
|
||||||
|
tag_a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
c: Expression<F>,
|
||||||
|
d: Expression<F>,
|
||||||
|
tag_d: Expression<F>,
|
||||||
|
word: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let decompose_check = a
|
||||||
|
+ b * F::from_u64(1 << 10)
|
||||||
|
+ c * F::from_u64(1 << 17)
|
||||||
|
+ d * F::from_u64(1 << 19)
|
||||||
|
+ word * (-F::one());
|
||||||
|
let range_check_tag_a = Gate::range_check(tag_a, 0, 1);
|
||||||
|
let range_check_tag_d = Gate::range_check(tag_d, 0, 3);
|
||||||
|
|
||||||
|
ScheduleGate(s_decompose_3 * (decompose_check + range_check_tag_a + range_check_tag_d))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// b_lo + 2^2 * b_mid = b, on W_[1..49]
|
||||||
|
fn check_b(b: Expression<F>, b_lo: Expression<F>, b_hi: Expression<F>) -> Expression<F> {
|
||||||
|
let expected_b = b_lo + b_hi * F::from_u64(1 << 2);
|
||||||
|
expected_b + (b * -F::one())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// b_lo + 2^2 * b_mid + 2^4 * b_hi = b, on W_[49..62]
|
||||||
|
fn check_b1(
|
||||||
|
b: Expression<F>,
|
||||||
|
b_lo: Expression<F>,
|
||||||
|
b_mid: Expression<F>,
|
||||||
|
b_hi: Expression<F>,
|
||||||
|
) -> Expression<F> {
|
||||||
|
let expected_b = b_lo + b_mid * F::from_u64(1 << 2) + b_hi * F::from_u64(1 << 4);
|
||||||
|
expected_b + (b * -F::one())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sigma_0 v1 on W_1 to W_13
|
||||||
|
/// (3, 4, 11, 14)-bit chunks
|
||||||
|
pub fn s_lower_sigma_0(
|
||||||
|
s_lower_sigma_0: Expression<F>,
|
||||||
|
spread_r0_even: Expression<F>,
|
||||||
|
spread_r0_odd: Expression<F>,
|
||||||
|
spread_r1_even: Expression<F>,
|
||||||
|
spread_r1_odd: Expression<F>,
|
||||||
|
a: Expression<F>,
|
||||||
|
spread_a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
b_lo: Expression<F>,
|
||||||
|
spread_b_lo: Expression<F>,
|
||||||
|
b_hi: Expression<F>,
|
||||||
|
spread_b_hi: Expression<F>,
|
||||||
|
spread_c: Expression<F>,
|
||||||
|
spread_d: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let check_spread_and_range =
|
||||||
|
Gate::two_bit_spread_and_range(b_lo.clone(), spread_b_lo.clone())
|
||||||
|
+ Gate::two_bit_spread_and_range(b_hi.clone(), spread_b_hi.clone())
|
||||||
|
+ Gate::three_bit_spread_and_range(a, spread_a.clone());
|
||||||
|
let check_b = Self::check_b(b, b_lo, b_hi);
|
||||||
|
let spread_witness = spread_r0_even
|
||||||
|
+ spread_r0_odd * F::from_u64(2)
|
||||||
|
+ (spread_r1_even + spread_r1_odd * F::from_u64(2)) * F::from_u64(1 << 32);
|
||||||
|
let xor_0 = spread_b_lo.clone()
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 4)
|
||||||
|
+ spread_c.clone() * F::from_u64(1 << 8)
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 30);
|
||||||
|
let xor_1 = spread_c.clone()
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 22)
|
||||||
|
+ spread_a.clone() * F::from_u64(1 << 50)
|
||||||
|
+ spread_b_lo.clone() * F::from_u64(1 << 56)
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 60);
|
||||||
|
let xor_2 = spread_d
|
||||||
|
+ spread_a * F::from_u64(1 << 28)
|
||||||
|
+ spread_b_lo * F::from_u64(1 << 34)
|
||||||
|
+ spread_b_hi * F::from_u64(1 << 38)
|
||||||
|
+ spread_c * F::from_u64(1 << 42);
|
||||||
|
let xor = xor_0 + xor_1 + xor_2;
|
||||||
|
|
||||||
|
ScheduleGate(
|
||||||
|
s_lower_sigma_0
|
||||||
|
* (check_spread_and_range + check_b + spread_witness + (xor * -F::one())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sigma_1 v1 on W_49 to W_61
|
||||||
|
/// (10, 7, 2, 13)-bit chunks
|
||||||
|
pub fn s_lower_sigma_1(
|
||||||
|
s_lower_sigma_1: Expression<F>,
|
||||||
|
spread_r0_even: Expression<F>,
|
||||||
|
spread_r0_odd: Expression<F>,
|
||||||
|
spread_r1_even: Expression<F>,
|
||||||
|
spread_r1_odd: Expression<F>,
|
||||||
|
spread_a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
b_lo: Expression<F>,
|
||||||
|
spread_b_lo: Expression<F>,
|
||||||
|
b_mid: Expression<F>,
|
||||||
|
spread_b_mid: Expression<F>,
|
||||||
|
b_hi: Expression<F>,
|
||||||
|
spread_b_hi: Expression<F>,
|
||||||
|
c: Expression<F>,
|
||||||
|
spread_c: Expression<F>,
|
||||||
|
spread_d: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let check_spread_and_range =
|
||||||
|
Gate::two_bit_spread_and_range(b_lo.clone(), spread_b_lo.clone())
|
||||||
|
+ Gate::two_bit_spread_and_range(b_mid.clone(), spread_b_mid.clone())
|
||||||
|
+ Gate::two_bit_spread_and_range(c, spread_c.clone())
|
||||||
|
+ Gate::three_bit_spread_and_range(b_hi.clone(), spread_b_hi.clone());
|
||||||
|
let check_b1 = Self::check_b1(b, b_lo, b_mid, b_hi);
|
||||||
|
let spread_witness = spread_r0_even
|
||||||
|
+ spread_r0_odd * F::from_u64(2)
|
||||||
|
+ (spread_r1_even + spread_r1_odd * F::from_u64(2)) * F::from_u64(1 << 32);
|
||||||
|
let xor_0 = spread_b_lo.clone()
|
||||||
|
+ spread_b_mid.clone() * F::from_u64(1 << 4)
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 8)
|
||||||
|
+ spread_c.clone() * F::from_u64(1 << 14)
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 18);
|
||||||
|
let xor_1 = spread_c.clone()
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 4)
|
||||||
|
+ spread_a.clone() * F::from_u64(1 << 30)
|
||||||
|
+ spread_b_lo.clone() * F::from_u64(1 << 50)
|
||||||
|
+ spread_b_mid.clone() * F::from_u64(1 << 54)
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 58);
|
||||||
|
let xor_2 = spread_d.clone()
|
||||||
|
+ spread_a.clone() * F::from_u64(1 << 26)
|
||||||
|
+ spread_b_lo.clone() * F::from_u64(1 << 46)
|
||||||
|
+ spread_b_mid.clone() * F::from_u64(1 << 50)
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 54)
|
||||||
|
+ spread_c.clone() * F::from_u64(1 << 60);
|
||||||
|
let xor = xor_0 + xor_1 + xor_2;
|
||||||
|
|
||||||
|
ScheduleGate(
|
||||||
|
s_lower_sigma_1
|
||||||
|
* (check_spread_and_range + check_b1 + spread_witness + (xor * -F::one())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sigma_0 v2 on W_14 to W_48
|
||||||
|
/// (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||||
|
pub fn s_lower_sigma_0_v2(
|
||||||
|
s_lower_sigma_0_v2: Expression<F>,
|
||||||
|
spread_r0_even: Expression<F>,
|
||||||
|
spread_r0_odd: Expression<F>,
|
||||||
|
spread_r1_even: Expression<F>,
|
||||||
|
spread_r1_odd: Expression<F>,
|
||||||
|
a: Expression<F>,
|
||||||
|
spread_a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
b_lo: Expression<F>,
|
||||||
|
spread_b_lo: Expression<F>,
|
||||||
|
b_hi: Expression<F>,
|
||||||
|
spread_b_hi: Expression<F>,
|
||||||
|
c: Expression<F>,
|
||||||
|
spread_c: Expression<F>,
|
||||||
|
spread_d: Expression<F>,
|
||||||
|
spread_e: Expression<F>,
|
||||||
|
spread_f: Expression<F>,
|
||||||
|
spread_g: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let check_spread_and_range =
|
||||||
|
Gate::two_bit_spread_and_range(b_lo.clone(), spread_b_lo.clone())
|
||||||
|
+ Gate::two_bit_spread_and_range(b_hi.clone(), spread_b_hi.clone())
|
||||||
|
+ Gate::three_bit_spread_and_range(a, spread_a.clone())
|
||||||
|
+ Gate::three_bit_spread_and_range(c, spread_c.clone());
|
||||||
|
let check_b = Self::check_b(b, b_lo, b_hi);
|
||||||
|
let spread_witness = spread_r0_even
|
||||||
|
+ spread_r0_odd * F::from_u64(2)
|
||||||
|
+ (spread_r1_even + spread_r1_odd * F::from_u64(2)) * F::from_u64(1 << 32);
|
||||||
|
let xor_0 = spread_b_lo.clone()
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 4)
|
||||||
|
+ spread_c.clone() * F::from_u64(1 << 8)
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 14)
|
||||||
|
+ spread_e.clone() * F::from_u64(1 << 28)
|
||||||
|
+ spread_f.clone() * F::from_u64(1 << 30)
|
||||||
|
+ spread_g.clone() * F::from_u64(1 << 32);
|
||||||
|
let xor_1 = spread_c.clone()
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 6)
|
||||||
|
+ spread_e.clone() * F::from_u64(1 << 20)
|
||||||
|
+ spread_f.clone() * F::from_u64(1 << 22)
|
||||||
|
+ spread_g.clone() * F::from_u64(1 << 24)
|
||||||
|
+ spread_a.clone() * F::from_u64(1 << 50)
|
||||||
|
+ spread_b_lo.clone() * F::from_u64(1 << 56)
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 60);
|
||||||
|
let xor_2 = spread_f
|
||||||
|
+ spread_g * F::from_u64(1 << 2)
|
||||||
|
+ spread_a * F::from_u64(1 << 28)
|
||||||
|
+ spread_b_lo * F::from_u64(1 << 34)
|
||||||
|
+ spread_b_hi * F::from_u64(1 << 38)
|
||||||
|
+ spread_c * F::from_u64(1 << 42)
|
||||||
|
+ spread_d * F::from_u64(1 << 48)
|
||||||
|
+ spread_e * F::from_u64(1 << 62);
|
||||||
|
let xor = xor_0 + xor_1 + xor_2;
|
||||||
|
|
||||||
|
ScheduleGate(
|
||||||
|
s_lower_sigma_0_v2
|
||||||
|
* (check_spread_and_range + check_b + spread_witness + (xor * -F::one())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// sigma_1 v2 on W_14 to W_48
|
||||||
|
/// (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||||
|
pub fn s_lower_sigma_1_v2(
|
||||||
|
s_lower_sigma_1_v2: Expression<F>,
|
||||||
|
spread_r0_even: Expression<F>,
|
||||||
|
spread_r0_odd: Expression<F>,
|
||||||
|
spread_r1_even: Expression<F>,
|
||||||
|
spread_r1_odd: Expression<F>,
|
||||||
|
a: Expression<F>,
|
||||||
|
spread_a: Expression<F>,
|
||||||
|
b: Expression<F>,
|
||||||
|
b_lo: Expression<F>,
|
||||||
|
spread_b_lo: Expression<F>,
|
||||||
|
b_hi: Expression<F>,
|
||||||
|
spread_b_hi: Expression<F>,
|
||||||
|
c: Expression<F>,
|
||||||
|
spread_c: Expression<F>,
|
||||||
|
spread_d: Expression<F>,
|
||||||
|
spread_e: Expression<F>,
|
||||||
|
spread_f: Expression<F>,
|
||||||
|
spread_g: Expression<F>,
|
||||||
|
) -> Self {
|
||||||
|
let check_spread_and_range =
|
||||||
|
Gate::two_bit_spread_and_range(b_lo.clone(), spread_b_lo.clone())
|
||||||
|
+ Gate::two_bit_spread_and_range(b_hi.clone(), spread_b_hi.clone())
|
||||||
|
+ Gate::three_bit_spread_and_range(a, spread_a.clone())
|
||||||
|
+ Gate::three_bit_spread_and_range(c, spread_c.clone());
|
||||||
|
let check_b = Self::check_b(b, b_lo, b_hi);
|
||||||
|
let spread_witness = spread_r0_even
|
||||||
|
+ spread_r0_odd * F::from_u64(2)
|
||||||
|
+ (spread_r1_even + spread_r1_odd * F::from_u64(2)) * F::from_u64(1 << 32);
|
||||||
|
let xor_0 = spread_d.clone()
|
||||||
|
+ spread_e.clone() * F::from_u64(1 << 14)
|
||||||
|
+ spread_f.clone() * F::from_u64(1 << 16)
|
||||||
|
+ spread_g.clone() * F::from_u64(1 << 18);
|
||||||
|
let xor_1 = spread_e.clone()
|
||||||
|
+ spread_f.clone() * F::from_u64(1 << 2)
|
||||||
|
+ spread_g.clone() * F::from_u64(1 << 4)
|
||||||
|
+ spread_a.clone() * F::from_u64(1 << 30)
|
||||||
|
+ spread_b_lo.clone() * F::from_u64(1 << 36)
|
||||||
|
+ spread_b_hi.clone() * F::from_u64(1 << 40)
|
||||||
|
+ spread_c.clone() * F::from_u64(1 << 44)
|
||||||
|
+ spread_d.clone() * F::from_u64(1 << 50);
|
||||||
|
let xor_2 = spread_g
|
||||||
|
+ spread_a * F::from_u64(1 << 26)
|
||||||
|
+ spread_b_lo * F::from_u64(1 << 32)
|
||||||
|
+ spread_b_hi * F::from_u64(1 << 36)
|
||||||
|
+ spread_c * F::from_u64(1 << 40)
|
||||||
|
+ spread_d * F::from_u64(1 << 46)
|
||||||
|
+ spread_e * F::from_u64(1 << 60)
|
||||||
|
+ spread_f * F::from_u64(1 << 62);
|
||||||
|
let xor = xor_0 + xor_1 + xor_2;
|
||||||
|
|
||||||
|
ScheduleGate(
|
||||||
|
s_lower_sigma_1_v2
|
||||||
|
* (check_spread_and_range + check_b + spread_witness + (xor * -F::one())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -514,7 +514,7 @@ mod tests {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let message_schedule = MessageSchedule::configure(
|
let message_schedule = MessageSchedule::empty_configure(
|
||||||
meta,
|
meta,
|
||||||
lookup_inputs.clone(),
|
lookup_inputs.clone(),
|
||||||
message_schedule,
|
message_schedule,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue