mirror of https://github.com/zcash/halo2.git
Remove unwrap()s in synthesis.
This commit is contained in:
parent
66268cf192
commit
ee5bc8184a
|
@ -47,21 +47,22 @@ fn bench(name: &str, k: u32, c: &mut Criterion) {
|
|||
|
||||
// Test vector: "abc"
|
||||
let test_input = [
|
||||
BlockWord::new(0b01100001011000100110001110000000),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord(Some(0b01100001011000100110001110000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000011000)),
|
||||
];
|
||||
|
||||
// Create a message of length 31 blocks
|
||||
|
|
|
@ -28,10 +28,7 @@ pub trait Sha256Instructions<F: FieldExt>: Chip<F> {
|
|||
type State: Clone + fmt::Debug;
|
||||
/// Variable representing a 32-bit word of the input block to the SHA-256 compression
|
||||
/// function.
|
||||
type BlockWord: Copy + fmt::Debug;
|
||||
|
||||
/// The zero BlockWord
|
||||
fn zero() -> Self::BlockWord;
|
||||
type BlockWord: Copy + fmt::Debug + Default;
|
||||
|
||||
/// Places the SHA-256 IV in the circuit, returning the initial state variable.
|
||||
fn initialization_vector(&self, layouter: &mut impl Layouter<F>) -> Result<Self::State, Error>;
|
||||
|
@ -140,7 +137,7 @@ impl<F: FieldExt, Sha256Chip: Sha256Instructions<F>> Sha256<F, Sha256Chip> {
|
|||
) -> Result<Sha256Digest<Sha256Chip::BlockWord>, Error> {
|
||||
// Pad the remaining block
|
||||
if !self.cur_block.is_empty() {
|
||||
let padding = vec![Sha256Chip::zero(); BLOCK_SIZE - self.cur_block.len()];
|
||||
let padding = vec![Sha256Chip::BlockWord::default(); BLOCK_SIZE - self.cur_block.len()];
|
||||
self.cur_block.extend_from_slice(&padding);
|
||||
self.state = self.chip.initialization(&mut layouter, &self.state)?;
|
||||
self.state = self.chip.compress(
|
||||
|
|
|
@ -44,21 +44,13 @@ const IV: [u32; STATE] = [
|
|||
0x5be0_cd19,
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
/// A word in a `Table16` message block.
|
||||
pub struct BlockWord {
|
||||
var: (),
|
||||
value: Option<u32>,
|
||||
}
|
||||
pub struct BlockWord(pub(crate) Option<u32>);
|
||||
|
||||
impl BlockWord {
|
||||
/// Create a new `BlockWord`.
|
||||
pub fn new(value: u32) -> Self {
|
||||
BlockWord {
|
||||
var: (),
|
||||
value: Some(value),
|
||||
}
|
||||
}
|
||||
pub trait CellValue<T> {
|
||||
fn var(&self) -> Cell;
|
||||
fn value(&self) -> Option<T>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -67,12 +59,18 @@ pub struct CellValue16 {
|
|||
value: Option<u16>,
|
||||
}
|
||||
|
||||
impl<F: FieldExt> CellValue<F> for CellValue16 {
|
||||
fn var(&self) -> Cell {
|
||||
self.var
|
||||
}
|
||||
fn value(&self) -> Option<F> {
|
||||
self.value.map(|value| F::from_u64(value as u64))
|
||||
}
|
||||
}
|
||||
|
||||
impl CellValue16 {
|
||||
pub fn new(var: Cell, value: u16) -> Self {
|
||||
CellValue16 {
|
||||
var,
|
||||
value: Some(value),
|
||||
}
|
||||
pub fn new(var: Cell, value: Option<u16>) -> Self {
|
||||
CellValue16 { var, value }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,18 +81,24 @@ pub struct CellValue32 {
|
|||
}
|
||||
|
||||
impl CellValue32 {
|
||||
pub fn new(var: Cell, value: u32) -> Self {
|
||||
CellValue32 {
|
||||
var,
|
||||
value: Some(value),
|
||||
}
|
||||
pub fn new(var: Cell, value: Option<u32>) -> Self {
|
||||
CellValue32 { var, value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FieldExt> CellValue<F> for CellValue32 {
|
||||
fn var(&self) -> Cell {
|
||||
self.var
|
||||
}
|
||||
fn value(&self) -> Option<F> {
|
||||
self.value.map(|value| F::from_u64(value as u64))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl Into<CellValue32> for CellValue16 {
|
||||
fn into(self) -> CellValue32 {
|
||||
CellValue32::new(self.var, self.value.unwrap() as u32)
|
||||
CellValue32::new(self.var, self.value.map(|value| value as u32))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,10 +197,6 @@ impl<F: FieldExt> Sha256Instructions<F> for Table16Chip<F> {
|
|||
type State = State;
|
||||
type BlockWord = BlockWord;
|
||||
|
||||
fn zero() -> Self::BlockWord {
|
||||
BlockWord::new(0)
|
||||
}
|
||||
|
||||
fn initialization_vector(&self, layouter: &mut impl Layouter<F>) -> Result<State, Error> {
|
||||
self.config().compression.initialize_with_iv(layouter, IV)
|
||||
}
|
||||
|
@ -248,34 +248,43 @@ trait Table16Assignment<F: FieldExt> {
|
|||
lookup: &SpreadInputs,
|
||||
a_3: Column<Advice>,
|
||||
row: usize,
|
||||
r_0_even: u16,
|
||||
r_0_odd: u16,
|
||||
r_1_even: u16,
|
||||
r_1_odd: u16,
|
||||
r_0_even: Option<u16>,
|
||||
r_0_odd: Option<u16>,
|
||||
r_1_even: Option<u16>,
|
||||
r_1_odd: Option<u16>,
|
||||
) -> Result<((CellValue16, CellValue16), (CellValue16, CellValue16)), Error> {
|
||||
// Lookup R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let r_0_even = SpreadVar::with_lookup(region, lookup, row - 1, SpreadWord::new(r_0_even))?;
|
||||
let r_0_odd = SpreadVar::with_lookup(region, lookup, row, SpreadWord::new(r_0_odd))?;
|
||||
let r_1_even = SpreadVar::with_lookup(region, lookup, row + 1, SpreadWord::new(r_1_even))?;
|
||||
let r_1_odd = SpreadVar::with_lookup(region, lookup, row + 2, SpreadWord::new(r_1_odd))?;
|
||||
let r_0_even =
|
||||
SpreadVar::with_lookup(region, lookup, row - 1, SpreadWord::opt_new(r_0_even))?;
|
||||
let r_0_odd = SpreadVar::with_lookup(region, lookup, row, SpreadWord::opt_new(r_0_odd))?;
|
||||
let r_1_even =
|
||||
SpreadVar::with_lookup(region, lookup, row + 1, SpreadWord::opt_new(r_1_even))?;
|
||||
let r_1_odd =
|
||||
SpreadVar::with_lookup(region, lookup, row + 2, SpreadWord::opt_new(r_1_odd))?;
|
||||
|
||||
// Assign and copy R_1^{odd}
|
||||
let r_1_odd_spread = region.assign_advice(
|
||||
|| "Assign and copy R_1^{odd}",
|
||||
a_3,
|
||||
row,
|
||||
|| Ok(F::from_u64(r_1_odd.spread.value.unwrap().into())),
|
||||
|| {
|
||||
r_1_odd
|
||||
.spread
|
||||
.value
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.constrain_equal(r_1_odd.spread.var, r_1_odd_spread)?;
|
||||
|
||||
Ok((
|
||||
(
|
||||
CellValue16::new(r_0_even.dense.var, r_0_even.dense.value.unwrap()),
|
||||
CellValue16::new(r_1_even.dense.var, r_1_even.dense.value.unwrap()),
|
||||
CellValue16::new(r_0_even.dense.var, r_0_even.dense.value),
|
||||
CellValue16::new(r_1_even.dense.var, r_1_even.dense.value),
|
||||
),
|
||||
(
|
||||
CellValue16::new(r_0_odd.dense.var, r_0_odd.dense.value.unwrap()),
|
||||
CellValue16::new(r_1_odd.dense.var, r_1_odd.dense.value.unwrap()),
|
||||
CellValue16::new(r_0_odd.dense.var, r_0_odd.dense.value),
|
||||
CellValue16::new(r_1_odd.dense.var, r_1_odd.dense.value),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -288,10 +297,10 @@ trait Table16Assignment<F: FieldExt> {
|
|||
lookup: &SpreadInputs,
|
||||
a_3: Column<Advice>,
|
||||
row: usize,
|
||||
r_0_even: u16,
|
||||
r_0_odd: u16,
|
||||
r_1_even: u16,
|
||||
r_1_odd: u16,
|
||||
r_0_even: Option<u16>,
|
||||
r_0_odd: Option<u16>,
|
||||
r_1_even: Option<u16>,
|
||||
r_1_odd: Option<u16>,
|
||||
) -> Result<(CellValue16, CellValue16), Error> {
|
||||
let (even, _odd) = self.assign_spread_outputs(
|
||||
region, lookup, a_3, row, r_0_even, r_0_odd, r_1_even, r_1_odd,
|
||||
|
@ -307,16 +316,16 @@ trait Table16Assignment<F: FieldExt> {
|
|||
annotation: A,
|
||||
column: Column<Advice>,
|
||||
row: usize,
|
||||
copy: &CellValue32,
|
||||
copy: impl CellValue<F>,
|
||||
) -> Result<Cell, Error>
|
||||
where
|
||||
A: Fn() -> AR,
|
||||
AR: Into<String>,
|
||||
{
|
||||
let cell = region.assign_advice(annotation, column, row, || {
|
||||
Ok(F::from_u64(copy.value.unwrap() as u64))
|
||||
copy.value().ok_or(Error::SynthesisError)
|
||||
})?;
|
||||
region.constrain_equal(cell, copy.var)?;
|
||||
region.constrain_equal(cell, copy.var())?;
|
||||
Ok(cell)
|
||||
}
|
||||
}
|
||||
|
@ -324,7 +333,7 @@ trait Table16Assignment<F: FieldExt> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{BlockWord, Sha256, BLOCK_SIZE};
|
||||
use super::{Table16Chip, Table16Config};
|
||||
use super::{message_schedule::msg_schedule_test_input, Table16Chip, Table16Config};
|
||||
use halo2::{
|
||||
arithmetic::FieldExt,
|
||||
circuit::{Layouter, SimpleFloorPlanner},
|
||||
|
@ -358,23 +367,7 @@ mod tests {
|
|||
Table16Chip::<F>::load(config, &mut layouter)?;
|
||||
|
||||
// Test vector: "abc"
|
||||
let test_input = [
|
||||
BlockWord::new(0b01100001011000100110001110000000),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
];
|
||||
let test_input = msg_schedule_test_input();
|
||||
|
||||
// Create a message of length 31 blocks
|
||||
let mut input = Vec::with_capacity(31 * BLOCK_SIZE);
|
||||
|
@ -419,23 +412,7 @@ mod tests {
|
|||
Table16Chip::<F>::load(config, &mut layouter)?;
|
||||
|
||||
// Test vector: "abc"
|
||||
let test_input = [
|
||||
BlockWord::new(0b01100001011000100110001110000000),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
BlockWord::new(0),
|
||||
];
|
||||
let test_input = msg_schedule_test_input();
|
||||
|
||||
// Create a message of length 2 blocks
|
||||
let mut input = Vec::with_capacity(2 * BLOCK_SIZE);
|
||||
|
|
|
@ -30,7 +30,7 @@ use compression_gates::CompressionGate;
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct AbcdVar {
|
||||
idx: i32,
|
||||
val: u32,
|
||||
val: Option<u32>,
|
||||
a: SpreadVar,
|
||||
b: SpreadVar,
|
||||
c_lo: SpreadVar,
|
||||
|
@ -52,7 +52,7 @@ pub struct AbcdVar {
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct EfghVar {
|
||||
idx: i32,
|
||||
val: u32,
|
||||
val: Option<u32>,
|
||||
a_lo: SpreadVar,
|
||||
a_hi: SpreadVar,
|
||||
b_lo: SpreadVar,
|
||||
|
@ -727,7 +727,7 @@ impl CompressionConfig {
|
|||
layouter: &mut impl Layouter<F>,
|
||||
state: State,
|
||||
) -> Result<[BlockWord; DIGEST_SIZE], Error> {
|
||||
let mut digest = [BlockWord::new(0); DIGEST_SIZE];
|
||||
let mut digest = [BlockWord(Some(0)); DIGEST_SIZE];
|
||||
layouter.assign_region(
|
||||
|| "digest",
|
||||
|mut region| {
|
||||
|
@ -743,7 +743,7 @@ impl CompressionConfig {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{
|
||||
super::BLOCK_SIZE, get_msg_schedule_test_input, BlockWord, Table16Chip, Table16Config, IV,
|
||||
super::BLOCK_SIZE, msg_schedule_test_input, BlockWord, Table16Chip, Table16Config, IV,
|
||||
};
|
||||
use halo2::{
|
||||
arithmetic::FieldExt,
|
||||
|
@ -777,7 +777,7 @@ mod tests {
|
|||
Table16Chip::<F>::load(config.clone(), &mut layouter)?;
|
||||
|
||||
// Test vector: "abc"
|
||||
let input: [BlockWord; BLOCK_SIZE] = get_msg_schedule_test_input();
|
||||
let input: [BlockWord; BLOCK_SIZE] = msg_schedule_test_input();
|
||||
|
||||
let (_, w_halves) = config.message_schedule.process(&mut layouter, input)?;
|
||||
|
||||
|
@ -792,7 +792,7 @@ mod tests {
|
|||
let digest = config.compression.digest(&mut layouter, state)?;
|
||||
for (idx, digest_word) in digest.iter().enumerate() {
|
||||
assert_eq!(
|
||||
(digest_word.value.unwrap() as u64 + IV[idx] as u64) as u32,
|
||||
(digest_word.0.unwrap() as u64 + IV[idx] as u64) as u32,
|
||||
super::compression_util::COMPRESSION_OUTPUT[idx]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::super::{
|
||||
util::*, CellValue16, CellValue32, SpreadVar, SpreadWord, StateWord, Table16Assignment,
|
||||
};
|
||||
use super::{
|
||||
AbcdVar, CompressionConfig, EfghVar, RoundWordA, RoundWordDense, RoundWordE, RoundWordSpread,
|
||||
State,
|
||||
};
|
||||
use crate::table16::{
|
||||
util::*, CellValue16, CellValue32, SpreadVar, SpreadWord, StateWord, Table16Assignment,
|
||||
};
|
||||
use halo2::{
|
||||
arithmetic::FieldExt,
|
||||
circuit::Region,
|
||||
|
@ -149,7 +149,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
row: usize,
|
||||
a_val: u32,
|
||||
a_val: Option<u32>,
|
||||
) -> Result<
|
||||
(
|
||||
SpreadVar,
|
||||
|
@ -173,10 +173,13 @@ impl CompressionConfig {
|
|||
let a_5 = self.message_schedule;
|
||||
let a_6 = self.extras[2];
|
||||
|
||||
let a_spread_pieces = chop_u32(a_val, &[2, 11, 3, 3, 3, 10])
|
||||
.iter()
|
||||
.map(|piece| SpreadWord::new(*piece as u16))
|
||||
.collect::<Vec<_>>();
|
||||
let a_spread_pieces = a_val.map(|a_val| {
|
||||
chop_u32(a_val, &[2, 11, 3, 3, 3, 10])
|
||||
.iter()
|
||||
.map(|piece| SpreadWord::new(*piece as u16))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let a_spread_pieces = transpose_option_vec(a_spread_pieces, 6);
|
||||
|
||||
let a = SpreadVar::without_lookup(region, a_3, row + 1, a_4, row + 1, a_spread_pieces[0])?;
|
||||
let b = SpreadVar::with_lookup(region, &self.lookup, row, a_spread_pieces[1])?;
|
||||
|
@ -193,7 +196,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
row: usize,
|
||||
val: u32,
|
||||
val: Option<u32>,
|
||||
) -> Result<
|
||||
(
|
||||
SpreadVar,
|
||||
|
@ -217,10 +220,13 @@ impl CompressionConfig {
|
|||
let a_5 = self.message_schedule;
|
||||
let a_6 = self.extras[2];
|
||||
|
||||
let spread_pieces = chop_u32(val, &[3, 3, 2, 3, 14, 7])
|
||||
.iter()
|
||||
.map(|piece| SpreadWord::new(*piece as u16))
|
||||
.collect::<Vec<_>>();
|
||||
let spread_pieces = val.map(|val| {
|
||||
chop_u32(val, &[3, 3, 2, 3, 14, 7])
|
||||
.iter()
|
||||
.map(|piece| SpreadWord::new(*piece as u16))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let spread_pieces = transpose_option_vec(spread_pieces, 6);
|
||||
|
||||
let a_lo = SpreadVar::without_lookup(region, a_3, row + 1, a_4, row + 1, spread_pieces[0])?;
|
||||
let a_hi = SpreadVar::without_lookup(region, a_5, row + 1, a_6, row + 1, spread_pieces[1])?;
|
||||
|
@ -236,7 +242,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
idx: i32,
|
||||
a_val: u32,
|
||||
a_val: Option<u32>,
|
||||
) -> Result<RoundWordA, Error> {
|
||||
let row = get_decompose_a_row(idx);
|
||||
|
||||
|
@ -259,7 +265,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
idx: i32,
|
||||
e_val: u32,
|
||||
e_val: Option<u32>,
|
||||
) -> Result<RoundWordE, Error> {
|
||||
let row = get_decompose_e_row(idx);
|
||||
|
||||
|
@ -299,48 +305,54 @@ impl CompressionConfig {
|
|||
)?;
|
||||
|
||||
// Assign `spread_a` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_a", a_3, row + 1, &word.a.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_a", a_3, row + 1, word.a.spread)?;
|
||||
// Assign `spread_b` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_b", a_5, row, &word.b.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_b", a_5, row, word.b.spread)?;
|
||||
// Assign `spread_c_lo` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_c_lo", a_3, row - 1, &word.c_lo.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_c_lo", a_3, row - 1, word.c_lo.spread)?;
|
||||
// Assign `spread_c_mid` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_c_mid", a_4, row - 1, &word.c_mid.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_c_mid", a_4, row - 1, word.c_mid.spread)?;
|
||||
// Assign `spread_c_hi` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_c_hi", a_4, row + 1, &word.c_hi.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_c_hi", a_4, row + 1, word.c_hi.spread)?;
|
||||
// Assign `spread_d` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_d", a_4, row, &word.d.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_d", a_4, row, word.d.spread)?;
|
||||
|
||||
// Calculate R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let spread_a = word.a.spread.value.unwrap() as u64;
|
||||
let spread_b = word.b.spread.value.unwrap() as u64;
|
||||
let spread_c_lo = word.c_lo.spread.value.unwrap() as u64;
|
||||
let spread_c_mid = word.c_mid.spread.value.unwrap() as u64;
|
||||
let spread_c_hi = word.c_hi.spread.value.unwrap() as u64;
|
||||
let spread_d = word.d.spread.value.unwrap() as u64;
|
||||
let (r_0_even, r_0_odd, r_1_even, r_1_odd) = if word.a.spread.value.is_some() {
|
||||
let spread_a = word.a.spread.value.unwrap() as u64;
|
||||
let spread_b = word.b.spread.value.unwrap() as u64;
|
||||
let spread_c_lo = word.c_lo.spread.value.unwrap() as u64;
|
||||
let spread_c_mid = word.c_mid.spread.value.unwrap() as u64;
|
||||
let spread_c_hi = word.c_hi.spread.value.unwrap() as u64;
|
||||
let spread_d = word.d.spread.value.unwrap() as u64;
|
||||
|
||||
let xor_0 = spread_b
|
||||
+ (1 << 22) * spread_c_lo
|
||||
+ (1 << 28) * spread_c_mid
|
||||
+ (1 << 34) * spread_c_hi
|
||||
+ (1 << 40) * spread_d
|
||||
+ (1 << 60) * spread_a;
|
||||
let xor_1 = spread_c_lo
|
||||
+ (1 << 6) * spread_c_mid
|
||||
+ (1 << 12) * spread_c_hi
|
||||
+ (1 << 18) * spread_d
|
||||
+ (1 << 38) * spread_a
|
||||
+ (1 << 42) * spread_b;
|
||||
let xor_2 = spread_d
|
||||
+ (1 << 20) * spread_a
|
||||
+ (1 << 24) * spread_b
|
||||
+ (1 << 46) * spread_c_lo
|
||||
+ (1 << 52) * spread_c_mid
|
||||
+ (1 << 58) * spread_c_hi;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
let xor_0 = spread_b
|
||||
+ (1 << 22) * spread_c_lo
|
||||
+ (1 << 28) * spread_c_mid
|
||||
+ (1 << 34) * spread_c_hi
|
||||
+ (1 << 40) * spread_d
|
||||
+ (1 << 60) * spread_a;
|
||||
let xor_1 = spread_c_lo
|
||||
+ (1 << 6) * spread_c_mid
|
||||
+ (1 << 12) * spread_c_hi
|
||||
+ (1 << 18) * spread_d
|
||||
+ (1 << 38) * spread_a
|
||||
+ (1 << 42) * spread_b;
|
||||
let xor_2 = spread_d
|
||||
+ (1 << 20) * spread_a
|
||||
+ (1 << 24) * spread_b
|
||||
+ (1 << 46) * spread_c_lo
|
||||
+ (1 << 52) * spread_c_mid
|
||||
+ (1 << 58) * spread_c_hi;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
|
||||
(Some(r_0_even), Some(r_0_odd), Some(r_1_even), Some(r_1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_sigma_outputs(
|
||||
region,
|
||||
|
@ -375,48 +387,54 @@ impl CompressionConfig {
|
|||
)?;
|
||||
|
||||
// Assign `spread_a_lo` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_a_lo", a_3, row + 1, &word.a_lo.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_a_lo", a_3, row + 1, word.a_lo.spread)?;
|
||||
// Assign `spread_a_hi` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_a_hi", a_4, row + 1, &word.a_hi.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_a_hi", a_4, row + 1, word.a_hi.spread)?;
|
||||
// Assign `spread_b_lo` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_b_lo", a_3, row - 1, &word.b_lo.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_b_lo", a_3, row - 1, word.b_lo.spread)?;
|
||||
// Assign `spread_b_hi` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_b_hi", a_4, row - 1, &word.b_hi.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_b_hi", a_4, row - 1, word.b_hi.spread)?;
|
||||
// Assign `spread_c` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_c", a_5, row, &word.c.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_c", a_5, row, word.c.spread)?;
|
||||
// Assign `spread_d` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_d", a_4, row, &word.d.spread)?;
|
||||
self.assign_and_constrain(region, || "spread_d", a_4, row, word.d.spread)?;
|
||||
|
||||
// Calculate R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let spread_a_lo = word.a_lo.spread.value.unwrap() as u64;
|
||||
let spread_a_hi = word.a_hi.spread.value.unwrap() as u64;
|
||||
let spread_b_lo = word.b_lo.spread.value.unwrap() as u64;
|
||||
let spread_b_hi = word.b_hi.spread.value.unwrap() as u64;
|
||||
let spread_c = word.c.spread.value.unwrap() as u64;
|
||||
let spread_d = word.d.spread.value.unwrap() as u64;
|
||||
let (r_0_even, r_0_odd, r_1_even, r_1_odd) = if word.a_lo.spread.value.is_some() {
|
||||
let spread_a_lo = word.a_lo.spread.value.unwrap() as u64;
|
||||
let spread_a_hi = word.a_hi.spread.value.unwrap() as u64;
|
||||
let spread_b_lo = word.b_lo.spread.value.unwrap() as u64;
|
||||
let spread_b_hi = word.b_hi.spread.value.unwrap() as u64;
|
||||
let spread_c = word.c.spread.value.unwrap() as u64;
|
||||
let spread_d = word.d.spread.value.unwrap() as u64;
|
||||
|
||||
let xor_0 = spread_b_lo
|
||||
+ (1 << 4) * spread_b_hi
|
||||
+ (1 << 10) * spread_c
|
||||
+ (1 << 38) * spread_d
|
||||
+ (1 << 52) * spread_a_lo
|
||||
+ (1 << 58) * spread_a_hi;
|
||||
let xor_1 = spread_c
|
||||
+ (1 << 28) * spread_d
|
||||
+ (1 << 42) * spread_a_lo
|
||||
+ (1 << 48) * spread_a_hi
|
||||
+ (1 << 54) * spread_b_lo
|
||||
+ (1 << 58) * spread_b_hi;
|
||||
let xor_2 = spread_d
|
||||
+ (1 << 14) * spread_a_lo
|
||||
+ (1 << 20) * spread_a_hi
|
||||
+ (1 << 26) * spread_b_lo
|
||||
+ (1 << 30) * spread_b_hi
|
||||
+ (1 << 36) * spread_c;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
let xor_0 = spread_b_lo
|
||||
+ (1 << 4) * spread_b_hi
|
||||
+ (1 << 10) * spread_c
|
||||
+ (1 << 38) * spread_d
|
||||
+ (1 << 52) * spread_a_lo
|
||||
+ (1 << 58) * spread_a_hi;
|
||||
let xor_1 = spread_c
|
||||
+ (1 << 28) * spread_d
|
||||
+ (1 << 42) * spread_a_lo
|
||||
+ (1 << 48) * spread_a_hi
|
||||
+ (1 << 54) * spread_b_lo
|
||||
+ (1 << 58) * spread_b_hi;
|
||||
let xor_2 = spread_d
|
||||
+ (1 << 14) * spread_a_lo
|
||||
+ (1 << 20) * spread_a_hi
|
||||
+ (1 << 26) * spread_b_lo
|
||||
+ (1 << 30) * spread_b_hi
|
||||
+ (1 << 36) * spread_c;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
|
||||
(Some(r_0_even), Some(r_0_odd), Some(r_1_even), Some(r_1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_sigma_outputs(
|
||||
region,
|
||||
|
@ -434,10 +452,10 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
row: usize,
|
||||
r_0_even: u16,
|
||||
r_0_odd: u16,
|
||||
r_1_even: u16,
|
||||
r_1_odd: u16,
|
||||
r_0_even: Option<u16>,
|
||||
r_0_odd: Option<u16>,
|
||||
r_1_even: Option<u16>,
|
||||
r_1_odd: Option<u16>,
|
||||
) -> Result<(CellValue16, CellValue16), Error> {
|
||||
let a_3 = self.extras[0];
|
||||
|
||||
|
@ -470,21 +488,27 @@ impl CompressionConfig {
|
|||
region.assign_fixed(|| "s_ch", self.s_ch, row, || Ok(F::one()))?;
|
||||
|
||||
// Assign and copy spread_e_lo, spread_e_hi
|
||||
self.assign_and_constrain(region, || "spread_e_lo", a_3, row - 1, &spread_halves_e.0)?;
|
||||
self.assign_and_constrain(region, || "spread_e_hi", a_4, row - 1, &spread_halves_e.1)?;
|
||||
self.assign_and_constrain(region, || "spread_e_lo", a_3, row - 1, spread_halves_e.0)?;
|
||||
self.assign_and_constrain(region, || "spread_e_hi", a_4, row - 1, spread_halves_e.1)?;
|
||||
|
||||
// Assign and copy spread_f_lo, spread_f_hi
|
||||
self.assign_and_constrain(region, || "spread_f_lo", a_3, row + 1, &spread_halves_f.0)?;
|
||||
self.assign_and_constrain(region, || "spread_f_hi", a_4, row + 1, &spread_halves_f.1)?;
|
||||
self.assign_and_constrain(region, || "spread_f_lo", a_3, row + 1, spread_halves_f.0)?;
|
||||
self.assign_and_constrain(region, || "spread_f_hi", a_4, row + 1, spread_halves_f.1)?;
|
||||
|
||||
let p: u64 = spread_halves_e.0.value.unwrap() as u64
|
||||
+ spread_halves_f.0.value.unwrap() as u64
|
||||
+ (1 << 32) * (spread_halves_e.1.value.unwrap() as u64)
|
||||
+ (1 << 32) * (spread_halves_f.1.value.unwrap() as u64);
|
||||
let p_pieces = chop_u64(p, &[32, 32]); // p_0, p_1
|
||||
let (p0_even, p0_odd, p1_even, p1_odd) = if spread_halves_e.0.value.is_some() {
|
||||
let p: u64 = spread_halves_e.0.value.unwrap() as u64
|
||||
+ spread_halves_f.0.value.unwrap() as u64
|
||||
+ (1 << 32) * (spread_halves_e.1.value.unwrap() as u64)
|
||||
+ (1 << 32) * (spread_halves_f.1.value.unwrap() as u64);
|
||||
let p_pieces = chop_u64(p, &[32, 32]); // p_0, p_1
|
||||
|
||||
let (p0_even, p0_odd) = get_even_and_odd_bits_u32(p_pieces[0] as u32);
|
||||
let (p1_even, p1_odd) = get_even_and_odd_bits_u32(p_pieces[1] as u32);
|
||||
let (p0_even, p0_odd) = get_even_and_odd_bits_u32(p_pieces[0] as u32);
|
||||
let (p1_even, p1_odd) = get_even_and_odd_bits_u32(p_pieces[1] as u32);
|
||||
|
||||
(Some(p0_even), Some(p0_odd), Some(p1_even), Some(p1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_ch_outputs(region, row, p0_even, p0_odd, p1_even, p1_odd)
|
||||
}
|
||||
|
@ -505,41 +529,59 @@ impl CompressionConfig {
|
|||
let a_5 = self.message_schedule;
|
||||
|
||||
// Assign and copy spread_e_lo, spread_e_hi
|
||||
self.assign_and_constrain(region, || "spread_e_lo", a_5, row - 1, &spread_halves_e.0)?;
|
||||
self.assign_and_constrain(region, || "spread_e_hi", a_5, row, &spread_halves_e.1)?;
|
||||
self.assign_and_constrain(region, || "spread_e_lo", a_5, row - 1, spread_halves_e.0)?;
|
||||
self.assign_and_constrain(region, || "spread_e_hi", a_5, row, spread_halves_e.1)?;
|
||||
|
||||
// Assign and copy spread_g_lo, spread_g_hi
|
||||
self.assign_and_constrain(region, || "spread_g_lo", a_3, row + 1, &spread_halves_g.0)?;
|
||||
self.assign_and_constrain(region, || "spread_g_hi", a_4, row + 1, &spread_halves_g.1)?;
|
||||
self.assign_and_constrain(region, || "spread_g_lo", a_3, row + 1, spread_halves_g.0)?;
|
||||
self.assign_and_constrain(region, || "spread_g_hi", a_4, row + 1, spread_halves_g.1)?;
|
||||
|
||||
// Calculate neg_e_lo, neg_e_hi
|
||||
let spread_e_lo = spread_halves_e.0.value.unwrap();
|
||||
let spread_e_hi = spread_halves_e.1.value.unwrap();
|
||||
let spread_neg_e_lo = (MASK_EVEN_32 - spread_e_lo) as u64;
|
||||
let spread_neg_e_hi = (MASK_EVEN_32 - spread_e_hi) as u64;
|
||||
let spread_neg_e_lo = spread_halves_e
|
||||
.0
|
||||
.value
|
||||
.map(|spread_e_lo| (MASK_EVEN_32 - spread_e_lo) as u64);
|
||||
let spread_neg_e_hi = spread_halves_e
|
||||
.1
|
||||
.value
|
||||
.map(|spread_e_hi| (MASK_EVEN_32 - spread_e_hi) as u64);
|
||||
|
||||
// Assign spread_neg_e_lo, spread_neg_e_hi
|
||||
region.assign_advice(
|
||||
|| "spread_neg_e_lo",
|
||||
a_3,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_neg_e_lo)),
|
||||
|| {
|
||||
spread_neg_e_lo
|
||||
.map(F::from_u64)
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "spread_neg_e_hi",
|
||||
a_4,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_neg_e_hi)),
|
||||
|| {
|
||||
spread_neg_e_hi
|
||||
.map(F::from_u64)
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
let p: u64 = spread_neg_e_lo
|
||||
+ spread_halves_g.0.value.unwrap() as u64
|
||||
+ (1 << 32) * spread_neg_e_hi
|
||||
+ (1 << 32) * (spread_halves_g.1.value.unwrap() as u64);
|
||||
let p_pieces = chop_u64(p, &[32, 32]); // p_0, p_1
|
||||
let (p0_even, p0_odd, p1_even, p1_odd) = if let Some(spread_neg_e_lo) = spread_neg_e_lo {
|
||||
let p: u64 = spread_neg_e_lo as u64
|
||||
+ spread_halves_g.0.value.unwrap() as u64
|
||||
+ (1 << 32) * spread_neg_e_hi.unwrap() as u64
|
||||
+ (1 << 32) * (spread_halves_g.1.value.unwrap() as u64);
|
||||
let p_pieces = chop_u64(p, &[32, 32]); // p_0, p_1
|
||||
|
||||
let (p0_even, p0_odd) = get_even_and_odd_bits_u32(p_pieces[0] as u32);
|
||||
let (p1_even, p1_odd) = get_even_and_odd_bits_u32(p_pieces[1] as u32);
|
||||
let (p0_even, p0_odd) = get_even_and_odd_bits_u32(p_pieces[0] as u32);
|
||||
let (p1_even, p1_odd) = get_even_and_odd_bits_u32(p_pieces[1] as u32);
|
||||
|
||||
(Some(p0_even), Some(p0_odd), Some(p1_even), Some(p1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_ch_outputs(region, row, p0_even, p0_odd, p1_even, p1_odd)
|
||||
}
|
||||
|
@ -548,10 +590,10 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
row: usize,
|
||||
r_0_even: u16,
|
||||
r_0_odd: u16,
|
||||
r_1_even: u16,
|
||||
r_1_odd: u16,
|
||||
r_0_even: Option<u16>,
|
||||
r_0_odd: Option<u16>,
|
||||
r_1_even: Option<u16>,
|
||||
r_1_odd: Option<u16>,
|
||||
) -> Result<(CellValue16, CellValue16), Error> {
|
||||
let a_3 = self.extras[0];
|
||||
let (_even, odd) = self.assign_spread_outputs(
|
||||
|
@ -584,27 +626,33 @@ impl CompressionConfig {
|
|||
region.assign_fixed(|| "s_maj", self.s_maj, row, || Ok(F::one()))?;
|
||||
|
||||
// Assign and copy spread_a_lo, spread_a_hi
|
||||
self.assign_and_constrain(region, || "spread_a_lo", a_4, row - 1, &spread_halves_a.0)?;
|
||||
self.assign_and_constrain(region, || "spread_a_hi", a_5, row - 1, &spread_halves_a.1)?;
|
||||
self.assign_and_constrain(region, || "spread_a_lo", a_4, row - 1, spread_halves_a.0)?;
|
||||
self.assign_and_constrain(region, || "spread_a_hi", a_5, row - 1, spread_halves_a.1)?;
|
||||
|
||||
// Assign and copy spread_b_lo, spread_b_hi
|
||||
self.assign_and_constrain(region, || "spread_b_lo", a_4, row, &spread_halves_b.0)?;
|
||||
self.assign_and_constrain(region, || "spread_b_hi", a_5, row, &spread_halves_b.1)?;
|
||||
self.assign_and_constrain(region, || "spread_b_lo", a_4, row, spread_halves_b.0)?;
|
||||
self.assign_and_constrain(region, || "spread_b_hi", a_5, row, spread_halves_b.1)?;
|
||||
|
||||
// Assign and copy spread_c_lo, spread_c_hi
|
||||
self.assign_and_constrain(region, || "spread_c_lo", a_4, row + 1, &spread_halves_c.0)?;
|
||||
self.assign_and_constrain(region, || "spread_c_hi", a_5, row + 1, &spread_halves_c.1)?;
|
||||
self.assign_and_constrain(region, || "spread_c_lo", a_4, row + 1, spread_halves_c.0)?;
|
||||
self.assign_and_constrain(region, || "spread_c_hi", a_5, row + 1, spread_halves_c.1)?;
|
||||
|
||||
let m: u64 = spread_halves_a.0.value.unwrap() as u64
|
||||
+ spread_halves_b.0.value.unwrap() as u64
|
||||
+ spread_halves_c.0.value.unwrap() as u64
|
||||
+ (1 << 32) * (spread_halves_a.1.value.unwrap() as u64)
|
||||
+ (1 << 32) * (spread_halves_b.1.value.unwrap() as u64)
|
||||
+ (1 << 32) * (spread_halves_c.1.value.unwrap() as u64);
|
||||
let m_pieces = chop_u64(m, &[32, 32]); // m_0, m_1
|
||||
let (m0_even, m0_odd, m1_even, m1_odd) = if spread_halves_a.0.value.is_some() {
|
||||
let m: u64 = spread_halves_a.0.value.unwrap() as u64
|
||||
+ spread_halves_b.0.value.unwrap() as u64
|
||||
+ spread_halves_c.0.value.unwrap() as u64
|
||||
+ (1 << 32) * (spread_halves_a.1.value.unwrap() as u64)
|
||||
+ (1 << 32) * (spread_halves_b.1.value.unwrap() as u64)
|
||||
+ (1 << 32) * (spread_halves_c.1.value.unwrap() as u64);
|
||||
let m_pieces = chop_u64(m, &[32, 32]); // m_0, m_1
|
||||
|
||||
let (m0_even, m0_odd) = get_even_and_odd_bits_u32(m_pieces[0] as u32);
|
||||
let (m1_even, m1_odd) = get_even_and_odd_bits_u32(m_pieces[1] as u32);
|
||||
let (m0_even, m0_odd) = get_even_and_odd_bits_u32(m_pieces[0] as u32);
|
||||
let (m1_even, m1_odd) = get_even_and_odd_bits_u32(m_pieces[1] as u32);
|
||||
|
||||
(Some(m0_even), Some(m0_odd), Some(m1_even), Some(m1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_maj_outputs(region, row, m0_even, m0_odd, m1_even, m1_odd)
|
||||
}
|
||||
|
@ -633,12 +681,12 @@ impl CompressionConfig {
|
|||
let a_9 = self.extras[5];
|
||||
|
||||
// Assign and copy h
|
||||
self.assign_and_constrain(region, || "h_lo", a_7, row - 1, &h.0.into())?;
|
||||
self.assign_and_constrain(region, || "h_hi", a_7, row, &h.1.into())?;
|
||||
self.assign_and_constrain(region, || "h_lo", a_7, row - 1, h.0)?;
|
||||
self.assign_and_constrain(region, || "h_hi", a_7, row, h.1)?;
|
||||
|
||||
// Assign and copy sigma_1
|
||||
self.assign_and_constrain(region, || "sigma_1_lo", a_4, row, &sigma_1.0.into())?;
|
||||
self.assign_and_constrain(region, || "sigma_1_hi", a_5, row, &sigma_1.1.into())?;
|
||||
self.assign_and_constrain(region, || "sigma_1_lo", a_4, row, sigma_1.0)?;
|
||||
self.assign_and_constrain(region, || "sigma_1_hi", a_5, row, sigma_1.1)?;
|
||||
|
||||
// Assign k
|
||||
let k_pieces = chop_u32(k, &[16, 16]);
|
||||
|
@ -651,57 +699,70 @@ impl CompressionConfig {
|
|||
region.assign_advice(|| "k_hi", a_6, row, || Ok(F::from_u64(k_pieces[1] as u64)))?;
|
||||
|
||||
// Assign and copy w
|
||||
self.assign_and_constrain(region, || "w_lo", a_8, row - 1, &w.0.into())?;
|
||||
self.assign_and_constrain(region, || "w_hi", a_8, row, &w.1.into())?;
|
||||
self.assign_and_constrain(region, || "w_lo", a_8, row - 1, w.0)?;
|
||||
self.assign_and_constrain(region, || "w_hi", a_8, row, w.1)?;
|
||||
|
||||
// Assign and copy ch
|
||||
self.assign_and_constrain(region, || "ch_neg_hi", a_6, row + 1, &ch.1.into())?;
|
||||
self.assign_and_constrain(region, || "ch_neg_hi", a_6, row + 1, ch.1)?;
|
||||
|
||||
// Assign and copy ch_neg
|
||||
self.assign_and_constrain(region, || "ch_neg_lo", a_5, row - 1, &ch_neg.0.into())?;
|
||||
self.assign_and_constrain(region, || "ch_neg_hi", a_5, row + 1, &ch_neg.1.into())?;
|
||||
self.assign_and_constrain(region, || "ch_neg_lo", a_5, row - 1, ch_neg.0)?;
|
||||
self.assign_and_constrain(region, || "ch_neg_hi", a_5, row + 1, ch_neg.1)?;
|
||||
|
||||
// Assign h_prime, h_prime_carry
|
||||
let h_prime_lo = h.0.value.unwrap() as u32
|
||||
+ ch.0.value.unwrap() as u32
|
||||
+ ch_neg.0.value.unwrap() as u32
|
||||
+ sigma_1.0.value.unwrap() as u32
|
||||
+ k_pieces[0]
|
||||
+ w.0.value.unwrap() as u32;
|
||||
let h_prime_hi = h.1.value.unwrap() as u32
|
||||
+ ch.1.value.unwrap() as u32
|
||||
+ ch_neg.1.value.unwrap() as u32
|
||||
+ sigma_1.1.value.unwrap() as u32
|
||||
+ k_pieces[1]
|
||||
+ w.1.value.unwrap() as u32;
|
||||
// Assign h_prime_lo, h_prime_hi, h_prime_carry
|
||||
let (h_prime, h_prime_carry) = sum_with_carry(vec![
|
||||
(h.0.value, h.1.value),
|
||||
(ch.0.value, ch.1.value),
|
||||
(ch_neg.0.value, ch_neg.1.value),
|
||||
(sigma_1.0.value, sigma_1.1.value),
|
||||
(Some(k_pieces[0] as u16), Some(k_pieces[1] as u16)),
|
||||
(w.0.value, w.1.value),
|
||||
]);
|
||||
let h_prime_halves = h_prime.map(|h_prime| chop_u32(h_prime as u32, &[16, 16]));
|
||||
let (h_prime_lo, h_prime_hi) = (
|
||||
h_prime_halves.clone().map(|halves| halves[0] as u16),
|
||||
h_prime_halves.map(|halves| halves[1] as u16),
|
||||
);
|
||||
|
||||
let h_prime: u64 = h_prime_lo as u64 + (1 << 16) * (h_prime_hi as u64);
|
||||
let h_prime_carry = h_prime >> 32;
|
||||
let h_prime_halves = chop_u32(h_prime as u32, &[16, 16]);
|
||||
let h_prime_lo = {
|
||||
let cell = region.assign_advice(
|
||||
|| "h_prime_lo",
|
||||
a_7,
|
||||
row + 1,
|
||||
|| {
|
||||
h_prime_lo
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
CellValue16::new(cell, h_prime_lo)
|
||||
};
|
||||
let h_prime_hi = {
|
||||
let cell = region.assign_advice(
|
||||
|| "h_prime_hi",
|
||||
a_8,
|
||||
row + 1,
|
||||
|| {
|
||||
h_prime_hi
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
CellValue16::new(cell, h_prime_hi)
|
||||
};
|
||||
|
||||
let h_prime_lo = region.assign_advice(
|
||||
|| "h_prime_lo",
|
||||
a_7,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(h_prime_halves[0] as u64)),
|
||||
)?;
|
||||
let h_prime_hi = region.assign_advice(
|
||||
|| "h_prime_hi",
|
||||
a_8,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(h_prime_halves[1] as u64)),
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "h_prime_carry",
|
||||
a_9,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(h_prime_carry as u64)),
|
||||
|| {
|
||||
h_prime_carry
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok((
|
||||
CellValue16::new(h_prime_lo, h_prime_halves[0] as u16),
|
||||
CellValue16::new(h_prime_hi, h_prime_halves[1] as u16),
|
||||
))
|
||||
Ok((h_prime_lo, h_prime_hi))
|
||||
}
|
||||
|
||||
// s_e_new to get E_new = H' + D
|
||||
|
@ -721,23 +782,21 @@ impl CompressionConfig {
|
|||
let a_9 = self.extras[5];
|
||||
|
||||
// Assign and copy d_lo, d_hi
|
||||
self.assign_and_constrain(region, || "d_lo", a_7, row, &d.0.into())?;
|
||||
self.assign_and_constrain(region, || "d_hi", a_7, row + 1, &d.1.into())?;
|
||||
self.assign_and_constrain(region, || "d_lo", a_7, row, d.0)?;
|
||||
self.assign_and_constrain(region, || "d_hi", a_7, row + 1, d.1)?;
|
||||
|
||||
// Assign e_new, e_new_carry
|
||||
let e_new_lo = h_prime.0.value.unwrap() as u32 + d.0.value.unwrap() as u32;
|
||||
let e_new_hi = h_prime.1.value.unwrap() as u32 + d.1.value.unwrap() as u32;
|
||||
|
||||
let e_new: u64 = e_new_lo as u64 + (1 << 16) * (e_new_hi as u64);
|
||||
let e_new_carry = e_new >> 32;
|
||||
let e_new: u32 = e_new as u32;
|
||||
let (e_new, e_new_carry) = sum_with_carry(vec![
|
||||
(h_prime.0.value, h_prime.1.value),
|
||||
(d.0.value, d.1.value),
|
||||
]);
|
||||
|
||||
let e_new_dense = self.assign_word_halves_dense(region, row, a_8, row + 1, a_8, e_new)?;
|
||||
region.assign_advice(
|
||||
|| "e_new_carry",
|
||||
a_9,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(e_new_carry as u64)),
|
||||
|| e_new_carry.map(F::from_u64).ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
|
||||
Ok(e_new_dense)
|
||||
|
@ -763,34 +822,29 @@ impl CompressionConfig {
|
|||
let a_9 = self.extras[5];
|
||||
|
||||
// Assign and copy maj_1
|
||||
self.assign_and_constrain(region, || "maj_1_hi", a_3, row - 1, &maj.1.into())?;
|
||||
self.assign_and_constrain(region, || "maj_1_hi", a_3, row - 1, maj.1)?;
|
||||
|
||||
// Assign and copy sigma_0
|
||||
self.assign_and_constrain(region, || "sigma_0_lo", a_6, row, &sigma_0.0.into())?;
|
||||
self.assign_and_constrain(region, || "sigma_0_hi", a_6, row + 1, &sigma_0.1.into())?;
|
||||
self.assign_and_constrain(region, || "sigma_0_lo", a_6, row, sigma_0.0)?;
|
||||
self.assign_and_constrain(region, || "sigma_0_hi", a_6, row + 1, sigma_0.1)?;
|
||||
|
||||
// Assign and copy h_prime
|
||||
self.assign_and_constrain(region, || "h_prime_lo", a_7, row - 1, &h_prime.0.into())?;
|
||||
self.assign_and_constrain(region, || "h_prime_hi", a_8, row - 1, &h_prime.1.into())?;
|
||||
self.assign_and_constrain(region, || "h_prime_lo", a_7, row - 1, h_prime.0)?;
|
||||
self.assign_and_constrain(region, || "h_prime_hi", a_8, row - 1, h_prime.1)?;
|
||||
|
||||
// Assign a_new, a_new_carry
|
||||
let a_new_lo = h_prime.0.value.unwrap() as u32
|
||||
+ sigma_0.0.value.unwrap() as u32
|
||||
+ maj.0.value.unwrap() as u32;
|
||||
let a_new_hi = h_prime.1.value.unwrap() as u32
|
||||
+ sigma_0.1.value.unwrap() as u32
|
||||
+ maj.1.value.unwrap() as u32;
|
||||
|
||||
let a_new: u64 = a_new_lo as u64 + (1 << 16) * (a_new_hi as u64);
|
||||
let a_new_carry = a_new >> 32;
|
||||
let a_new: u32 = a_new as u32;
|
||||
let (a_new, a_new_carry) = sum_with_carry(vec![
|
||||
(h_prime.0.value, h_prime.1.value),
|
||||
(sigma_0.0.value, sigma_0.1.value),
|
||||
(maj.0.value, maj.1.value),
|
||||
]);
|
||||
|
||||
let a_new_dense = self.assign_word_halves_dense(region, row, a_8, row + 1, a_8, a_new)?;
|
||||
region.assign_advice(
|
||||
|| "a_new_carry",
|
||||
a_9,
|
||||
row,
|
||||
|| Ok(F::from_u64(a_new_carry as u64)),
|
||||
|| a_new_carry.map(F::from_u64).ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
|
||||
Ok(a_new_dense)
|
||||
|
@ -803,25 +857,40 @@ impl CompressionConfig {
|
|||
lo_col: Column<Advice>,
|
||||
hi_row: usize,
|
||||
hi_col: Column<Advice>,
|
||||
word: u32,
|
||||
word: Option<u32>,
|
||||
) -> Result<(CellValue16, CellValue16), Error> {
|
||||
let halves = chop_u32(word, &[16, 16]);
|
||||
let lo = region.assign_advice(
|
||||
|| "lo",
|
||||
lo_col,
|
||||
lo_row,
|
||||
|| Ok(F::from_u64(halves[0] as u64)),
|
||||
)?;
|
||||
let hi = region.assign_advice(
|
||||
|| "hi",
|
||||
hi_col,
|
||||
hi_row,
|
||||
|| Ok(F::from_u64(halves[1] as u64)),
|
||||
)?;
|
||||
let w_lo_cell = CellValue16::new(lo, halves[0] as u16);
|
||||
let w_hi_cell = CellValue16::new(hi, halves[1] as u16);
|
||||
let (lo, hi) = if let Some(word) = word {
|
||||
let halves = chop_u32(word, &[16, 16]);
|
||||
(Some(halves[0] as u16), Some(halves[1] as u16))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
let lo = {
|
||||
let cell = region.assign_advice(
|
||||
|| "lo",
|
||||
lo_col,
|
||||
lo_row,
|
||||
|| {
|
||||
lo.map(|lo| F::from_u64(lo as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
CellValue16::new(cell, lo)
|
||||
};
|
||||
let hi = {
|
||||
let cell = region.assign_advice(
|
||||
|| "hi",
|
||||
hi_col,
|
||||
hi_row,
|
||||
|| {
|
||||
hi.map(|hi| F::from_u64(hi as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
CellValue16::new(cell, hi)
|
||||
};
|
||||
|
||||
Ok((w_lo_cell, w_hi_cell))
|
||||
Ok((lo, hi))
|
||||
}
|
||||
|
||||
// Assign hi and lo halves for both dense and spread versions of a word
|
||||
|
@ -830,30 +899,35 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
row: usize,
|
||||
word: u32,
|
||||
word: Option<u32>,
|
||||
) -> Result<((CellValue16, CellValue16), (CellValue32, CellValue32)), Error> {
|
||||
// Rename these here for ease of matching the gates to the specification.
|
||||
let a_7 = self.extras[3];
|
||||
let a_8 = self.extras[4];
|
||||
|
||||
let halves = chop_u32(word, &[16, 16]);
|
||||
let w_lo = SpreadWord::new(halves[0] as u16);
|
||||
let w_hi = SpreadWord::new(halves[1] as u16);
|
||||
let halves = word.map(|word| chop_u32(word, &[16, 16]));
|
||||
let halves = transpose_option_vec(halves, 2);
|
||||
let w_lo = SpreadWord::opt_new(halves[0].map(|value| value as u16));
|
||||
let w_hi = SpreadWord::opt_new(halves[1].map(|value| value as u16));
|
||||
|
||||
let w_lo = SpreadVar::without_lookup(region, a_7, row, a_8, row, w_lo)?;
|
||||
let w_hi = SpreadVar::without_lookup(region, a_7, row + 1, a_8, row + 1, w_hi)?;
|
||||
|
||||
let w_lo_cell = CellValue16::new(w_lo.dense.var, w_lo.dense.value.unwrap());
|
||||
let w_hi_cell = CellValue16::new(w_hi.dense.var, w_hi.dense.value.unwrap());
|
||||
let spread_w_lo_cell = CellValue32::new(w_lo.spread.var, w_lo.spread.value.unwrap());
|
||||
let spread_w_hi_cell = CellValue32::new(w_hi.spread.var, w_hi.spread.value.unwrap());
|
||||
let w_lo_cell = CellValue16::new(w_lo.dense.var, w_lo.dense.value);
|
||||
let w_hi_cell = CellValue16::new(w_hi.dense.var, w_hi.dense.value);
|
||||
let spread_w_lo_cell = CellValue32::new(w_lo.spread.var, w_lo.spread.value);
|
||||
let spread_w_hi_cell = CellValue32::new(w_hi.spread.var, w_hi.spread.value);
|
||||
|
||||
Ok(((w_lo_cell, w_hi_cell), (spread_w_lo_cell, spread_w_hi_cell)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn val_from_dense_halves(dense_halves: (CellValue16, CellValue16)) -> u32 {
|
||||
dense_halves.0.value.unwrap() as u32 + (1 << 16) * dense_halves.1.value.unwrap() as u32
|
||||
pub fn val_from_dense_halves(dense_halves: (CellValue16, CellValue16)) -> Option<u32> {
|
||||
dense_halves
|
||||
.0
|
||||
.value
|
||||
.zip(dense_halves.1.value)
|
||||
.map(|(lo, hi)| lo as u32 + (1 << 16) * hi as u32)
|
||||
}
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
|
|
|
@ -28,36 +28,50 @@ impl CompressionConfig {
|
|||
region.assign_fixed(|| "s_digest", self.s_digest, efgh_row, || Ok(F::one()))?;
|
||||
|
||||
// Assign digest for A, B, C, D
|
||||
self.assign_and_constrain(region, || "a_lo", a_3, abcd_row, &a.dense_halves.0.into())?;
|
||||
self.assign_and_constrain(region, || "a_hi", a_4, abcd_row, &a.dense_halves.1.into())?;
|
||||
let a = a.dense_halves.0.value.unwrap() as u32
|
||||
+ (1 << 16) * (a.dense_halves.1.value.unwrap() as u32);
|
||||
region.assign_advice(|| "a", a_5, abcd_row, || Ok(F::from_u64(a as u64)))?;
|
||||
self.assign_and_constrain(region, || "a_lo", a_3, abcd_row, a.dense_halves.0)?;
|
||||
self.assign_and_constrain(region, || "a_hi", a_4, abcd_row, a.dense_halves.1)?;
|
||||
let a = val_from_dense_halves(a.dense_halves);
|
||||
region.assign_advice(
|
||||
|| "a",
|
||||
a_5,
|
||||
abcd_row,
|
||||
|| {
|
||||
a.map(|a| F::from_u64(a as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
let b = self.assign_digest_word(region, abcd_row, a_6, a_7, a_8, b.dense_halves)?;
|
||||
let c = self.assign_digest_word(region, abcd_row + 1, a_3, a_4, a_5, c.dense_halves)?;
|
||||
let d = self.assign_digest_word(region, abcd_row + 1, a_6, a_7, a_8, d.dense_halves)?;
|
||||
|
||||
// Assign digest for E, F, G, H
|
||||
self.assign_and_constrain(region, || "e_lo", a_3, efgh_row, &e.dense_halves.0.into())?;
|
||||
self.assign_and_constrain(region, || "e_hi", a_4, efgh_row, &e.dense_halves.1.into())?;
|
||||
let e = e.dense_halves.0.value.unwrap() as u32
|
||||
+ (1 << 16) * (e.dense_halves.1.value.unwrap() as u32);
|
||||
region.assign_advice(|| "e", a_5, efgh_row, || Ok(F::from_u64(e as u64)))?;
|
||||
self.assign_and_constrain(region, || "e_lo", a_3, efgh_row, e.dense_halves.0)?;
|
||||
self.assign_and_constrain(region, || "e_hi", a_4, efgh_row, e.dense_halves.1)?;
|
||||
let e = val_from_dense_halves(e.dense_halves);
|
||||
region.assign_advice(
|
||||
|| "e",
|
||||
a_5,
|
||||
efgh_row,
|
||||
|| {
|
||||
e.map(|e| F::from_u64(e as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
let f = self.assign_digest_word(region, efgh_row, a_6, a_7, a_8, f.dense_halves)?;
|
||||
let g = self.assign_digest_word(region, efgh_row + 1, a_3, a_4, a_5, g.dense_halves)?;
|
||||
let h = self.assign_digest_word(region, efgh_row + 1, a_6, a_7, a_8, h.dense_halves)?;
|
||||
|
||||
Ok([
|
||||
BlockWord::new(a),
|
||||
BlockWord::new(b),
|
||||
BlockWord::new(c),
|
||||
BlockWord::new(d),
|
||||
BlockWord::new(e),
|
||||
BlockWord::new(f),
|
||||
BlockWord::new(g),
|
||||
BlockWord::new(h),
|
||||
BlockWord(a),
|
||||
BlockWord(b),
|
||||
BlockWord(c),
|
||||
BlockWord(d),
|
||||
BlockWord(e),
|
||||
BlockWord(f),
|
||||
BlockWord(g),
|
||||
BlockWord(h),
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -69,12 +83,20 @@ impl CompressionConfig {
|
|||
hi_col: Column<Advice>,
|
||||
word_col: Column<Advice>,
|
||||
dense_halves: (CellValue16, CellValue16),
|
||||
) -> Result<u32, Error> {
|
||||
self.assign_and_constrain(region, || "lo", lo_col, row, &dense_halves.0.into())?;
|
||||
self.assign_and_constrain(region, || "hi", hi_col, row, &dense_halves.1.into())?;
|
||||
let val = dense_halves.0.value.unwrap() as u32
|
||||
+ (1 << 16) * (dense_halves.1.value.unwrap() as u32);
|
||||
region.assign_advice(|| "word", word_col, row, || Ok(F::from_u64(val as u64)))?;
|
||||
) -> Result<Option<u32>, Error> {
|
||||
self.assign_and_constrain(region, || "lo", lo_col, row, dense_halves.0)?;
|
||||
self.assign_and_constrain(region, || "hi", hi_col, row, dense_halves.1)?;
|
||||
|
||||
let val = val_from_dense_halves(dense_halves);
|
||||
region.assign_advice(
|
||||
|| "word",
|
||||
word_col,
|
||||
row,
|
||||
|| {
|
||||
val.map(|val| F::from_u64(val as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(val)
|
||||
}
|
||||
|
|
|
@ -14,27 +14,29 @@ impl CompressionConfig {
|
|||
let idx = -1;
|
||||
|
||||
// Decompose E into (6, 5, 14, 7)-bit chunks
|
||||
let e = self.decompose_e(region, idx, iv[4])?;
|
||||
let e = self.decompose_e(region, idx, Some(iv[4]))?;
|
||||
|
||||
// Decompose F, G
|
||||
let f = self.decompose_f(region, idx, iv[5])?;
|
||||
let g = self.decompose_g(region, idx, iv[6])?;
|
||||
let f = self.decompose_f(region, idx, Some(iv[5]))?;
|
||||
let g = self.decompose_g(region, idx, Some(iv[6]))?;
|
||||
|
||||
// Assign H
|
||||
let h_row = get_h_row(idx);
|
||||
let h_dense = self.assign_word_halves_dense(region, h_row, a_7, h_row + 1, a_7, iv[7])?;
|
||||
let h_dense =
|
||||
self.assign_word_halves_dense(region, h_row, a_7, h_row + 1, a_7, Some(iv[7]))?;
|
||||
let h = RoundWordDense::new(h_dense);
|
||||
|
||||
// Decompose A into (2, 11, 9, 10)-bit chunks
|
||||
let a = self.decompose_a(region, idx, iv[0])?;
|
||||
let a = self.decompose_a(region, idx, Some(iv[0]))?;
|
||||
|
||||
// Decompose B, C
|
||||
let b = self.decompose_b(region, idx, iv[1])?;
|
||||
let c = self.decompose_c(region, idx, iv[2])?;
|
||||
let b = self.decompose_b(region, idx, Some(iv[1]))?;
|
||||
let c = self.decompose_c(region, idx, Some(iv[2]))?;
|
||||
|
||||
// Assign D
|
||||
let d_row = get_d_row(idx);
|
||||
let d_dense = self.assign_word_halves_dense(region, d_row, a_7, d_row + 1, a_7, iv[3])?;
|
||||
let d_dense =
|
||||
self.assign_word_halves_dense(region, d_row, a_7, d_row + 1, a_7, Some(iv[3]))?;
|
||||
let d = RoundWordDense::new(d_dense);
|
||||
|
||||
Ok(State::new(
|
||||
|
@ -108,7 +110,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
idx: i32,
|
||||
b_val: u32,
|
||||
b_val: Option<u32>,
|
||||
) -> Result<RoundWordSpread, Error> {
|
||||
let row = get_decompose_b_row(idx);
|
||||
|
||||
|
@ -121,7 +123,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
idx: i32,
|
||||
c_val: u32,
|
||||
c_val: Option<u32>,
|
||||
) -> Result<RoundWordSpread, Error> {
|
||||
let row = get_decompose_c_row(idx);
|
||||
|
||||
|
@ -134,7 +136,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
idx: i32,
|
||||
f_val: u32,
|
||||
f_val: Option<u32>,
|
||||
) -> Result<RoundWordSpread, Error> {
|
||||
let row = get_decompose_f_row(idx);
|
||||
|
||||
|
@ -147,7 +149,7 @@ impl CompressionConfig {
|
|||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
idx: i32,
|
||||
g_val: u32,
|
||||
g_val: Option<u32>,
|
||||
) -> Result<RoundWordSpread, Error> {
|
||||
let row = get_decompose_g_row(idx);
|
||||
|
||||
|
|
|
@ -61,37 +61,13 @@ impl CompressionConfig {
|
|||
if idx < 63 {
|
||||
// Assign and copy A_new
|
||||
let a_new_row = get_decompose_a_row(idx + 1);
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| "a_new_lo",
|
||||
a_7,
|
||||
a_new_row,
|
||||
&a_new_dense.0.into(),
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| "a_new_hi",
|
||||
a_7,
|
||||
a_new_row + 1,
|
||||
&a_new_dense.1.into(),
|
||||
)?;
|
||||
self.assign_and_constrain(region, || "a_new_lo", a_7, a_new_row, a_new_dense.0)?;
|
||||
self.assign_and_constrain(region, || "a_new_hi", a_7, a_new_row + 1, a_new_dense.1)?;
|
||||
|
||||
// Assign and copy E_new
|
||||
let e_new_row = get_decompose_e_row(idx + 1);
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| "e_new_lo",
|
||||
a_7,
|
||||
e_new_row,
|
||||
&e_new_dense.0.into(),
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| "e_new_hi",
|
||||
a_7,
|
||||
e_new_row + 1,
|
||||
&e_new_dense.1.into(),
|
||||
)?;
|
||||
self.assign_and_constrain(region, || "e_new_lo", a_7, e_new_row, e_new_dense.0)?;
|
||||
self.assign_and_constrain(region, || "e_new_hi", a_7, e_new_row + 1, e_new_dense.1)?;
|
||||
|
||||
// Decompose A into (2, 11, 9, 10)-bit chunks
|
||||
let a_new = self.decompose_a(region, idx + 1, a_new_val)?;
|
||||
|
|
|
@ -18,7 +18,7 @@ use schedule_gates::ScheduleGate;
|
|||
use schedule_util::*;
|
||||
|
||||
#[cfg(test)]
|
||||
pub use schedule_util::get_msg_schedule_test_input;
|
||||
pub use schedule_util::msg_schedule_test_input;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct MessageWord {
|
||||
|
@ -394,12 +394,8 @@ impl MessageScheduleConfig {
|
|||
|
||||
// Assign W[0..16]
|
||||
for (i, word) in input.iter().enumerate() {
|
||||
let (var, halves) =
|
||||
self.assign_word_and_halves(&mut region, word.value.unwrap(), i)?;
|
||||
w.push(MessageWord {
|
||||
var,
|
||||
value: word.value,
|
||||
});
|
||||
let (var, halves) = self.assign_word_and_halves(&mut region, word.0, i)?;
|
||||
w.push(MessageWord { var, value: word.0 });
|
||||
w_halves.push(halves);
|
||||
}
|
||||
|
||||
|
@ -469,7 +465,7 @@ mod tests {
|
|||
|
||||
// Provide input
|
||||
// Test vector: "abc"
|
||||
let inputs: [BlockWord; BLOCK_SIZE] = get_msg_schedule_test_input();
|
||||
let inputs: [BlockWord; BLOCK_SIZE] = msg_schedule_test_input();
|
||||
|
||||
// Run message_scheduler to get W_[0..64]
|
||||
let (w, _) = config.message_schedule.process(&mut layouter, inputs)?;
|
||||
|
|
|
@ -59,24 +59,24 @@ pub fn get_word_row(word_idx: usize) -> usize {
|
|||
|
||||
/// Test vector: "abc"
|
||||
#[cfg(test)]
|
||||
pub fn get_msg_schedule_test_input() -> [BlockWord; BLOCK_SIZE] {
|
||||
pub fn msg_schedule_test_input() -> [BlockWord; BLOCK_SIZE] {
|
||||
[
|
||||
BlockWord::new(0b01100001011000100110001110000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000000000),
|
||||
BlockWord::new(0b00000000000000000000000000011000),
|
||||
BlockWord(Some(0b01100001011000100110001110000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000000000)),
|
||||
BlockWord(Some(0b00000000000000000000000000011000)),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ impl MessageScheduleConfig {
|
|||
pub fn assign_word_and_halves<F: FieldExt>(
|
||||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
word: u32,
|
||||
word: Option<u32>,
|
||||
word_idx: usize,
|
||||
) -> Result<(Cell, (CellValue16, CellValue16)), Error> {
|
||||
// Rename these here for ease of matching the gates to the specification.
|
||||
|
@ -162,35 +162,45 @@ impl MessageScheduleConfig {
|
|||
|
||||
let row = get_word_row(word_idx);
|
||||
|
||||
let var = region.assign_advice(
|
||||
|| format!("W_{}", word_idx),
|
||||
self.message_schedule,
|
||||
row,
|
||||
|| Ok(F::from_u64(word as u64)),
|
||||
)?;
|
||||
let var = {
|
||||
let word = word.map(|word| F::from_u64(word as u64));
|
||||
region.assign_advice(
|
||||
|| format!("W_{}", word_idx),
|
||||
self.message_schedule,
|
||||
row,
|
||||
|| word.ok_or(Error::SynthesisError),
|
||||
)?
|
||||
};
|
||||
|
||||
let w_lo = word as u16;
|
||||
let w_hi = (word >> 16) as u16;
|
||||
let w_lo = {
|
||||
let w_lo_val = word.map(|word| word as u16);
|
||||
let w_lo_cell = region.assign_advice(
|
||||
|| format!("W_{}_lo", word_idx),
|
||||
a_3,
|
||||
row,
|
||||
|| {
|
||||
w_lo_val
|
||||
.map(|w_lo| F::from_u64(w_lo as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
CellValue16::new(w_lo_cell, w_lo_val)
|
||||
};
|
||||
let w_hi = {
|
||||
let w_hi_val = word.map(|word| (word >> 16) as u16);
|
||||
let w_hi_cell = region.assign_advice(
|
||||
|| format!("W_{}_hi", word_idx),
|
||||
a_4,
|
||||
row,
|
||||
|| {
|
||||
w_hi_val
|
||||
.map(|w_hi| F::from_u64(w_hi as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
CellValue16::new(w_hi_cell, w_hi_val)
|
||||
};
|
||||
|
||||
let w_lo_cell = region.assign_advice(
|
||||
|| format!("W_{}_lo", word_idx),
|
||||
a_3,
|
||||
row,
|
||||
|| Ok(F::from_u64(w_lo as u64)),
|
||||
)?;
|
||||
let w_hi_cell = region.assign_advice(
|
||||
|| format!("W_{}_hi", word_idx),
|
||||
a_4,
|
||||
row,
|
||||
|| Ok(F::from_u64(w_hi as u64)),
|
||||
)?;
|
||||
|
||||
Ok((
|
||||
var,
|
||||
(
|
||||
CellValue16::new(w_lo_cell, w_lo),
|
||||
CellValue16::new(w_hi_cell, w_hi),
|
||||
),
|
||||
))
|
||||
Ok((var, (w_lo, w_hi)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ pub struct Subregion1Word {
|
|||
index: usize,
|
||||
a: CellValue32,
|
||||
b: CellValue32,
|
||||
c: CellValue32,
|
||||
d: CellValue32,
|
||||
c: CellValue16,
|
||||
d: CellValue16,
|
||||
spread_c: CellValue32,
|
||||
spread_d: CellValue32,
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ impl MessageScheduleConfig {
|
|||
.map(|(idx, word)| {
|
||||
// s_decompose_1 on W_[1..14]
|
||||
let subregion1_word = self
|
||||
.decompose_subregion1_word(region, word.value.unwrap(), idx + 1)
|
||||
.decompose_subregion1_word(region, word.0, idx + 1)
|
||||
.unwrap();
|
||||
|
||||
// lower_sigma_0 on W_[1..14]
|
||||
|
@ -42,7 +42,7 @@ impl MessageScheduleConfig {
|
|||
fn decompose_subregion1_word<F: FieldExt>(
|
||||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
word: u32,
|
||||
word: Option<u32>,
|
||||
index: usize,
|
||||
) -> Result<Subregion1Word, Error> {
|
||||
let row = get_word_row(index);
|
||||
|
@ -51,39 +51,48 @@ impl MessageScheduleConfig {
|
|||
let a_3 = self.extras[0];
|
||||
let a_4 = self.extras[1];
|
||||
|
||||
let pieces = chop_u32(word, &[3, 4, 11, 14]);
|
||||
let pieces = word.map(|word| chop_u32(word, &[3, 4, 11, 14]));
|
||||
let pieces = transpose_option_vec(pieces, 4);
|
||||
|
||||
// Assign `a` (3-bit piece)
|
||||
let a = region.assign_advice(
|
||||
|| "word_a",
|
||||
a_3,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(pieces[0] as u64)),
|
||||
|| {
|
||||
pieces[0]
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
// Assign `b` (4-bit piece)
|
||||
let b = region.assign_advice(
|
||||
|| "word_b",
|
||||
a_4,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(pieces[1] as u64)),
|
||||
|| {
|
||||
pieces[1]
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `c` (11-bit piece) lookup
|
||||
let spread_c = SpreadWord::new(pieces[2] as u16);
|
||||
let spread_c = SpreadWord::opt_new(pieces[2].map(|value| value as u16));
|
||||
let spread_c = SpreadVar::with_lookup(region, &self.lookup, row + 1, spread_c)?;
|
||||
|
||||
// Assign `d` (14-bit piece) lookup
|
||||
let spread_d = SpreadWord::new(pieces[3] as u16);
|
||||
let spread_d = SpreadWord::opt_new(pieces[3].map(|value| value as u16));
|
||||
let spread_d = SpreadVar::with_lookup(region, &self.lookup, row, spread_d)?;
|
||||
|
||||
Ok(Subregion1Word {
|
||||
index,
|
||||
a: CellValue32::new(a, pieces[0]),
|
||||
b: CellValue32::new(b, pieces[1]),
|
||||
c: CellValue32::new(spread_c.dense.var, spread_c.dense.value.unwrap().into()),
|
||||
d: CellValue32::new(spread_d.dense.var, spread_d.dense.value.unwrap().into()),
|
||||
spread_c: CellValue32::new(spread_c.spread.var, spread_c.spread.value.unwrap()),
|
||||
spread_d: CellValue32::new(spread_d.spread.var, spread_d.spread.value.unwrap()),
|
||||
c: CellValue16::new(spread_c.dense.var, spread_c.dense.value),
|
||||
d: CellValue16::new(spread_d.dense.var, spread_d.dense.value),
|
||||
spread_c: CellValue32::new(spread_c.spread.var, spread_c.spread.value),
|
||||
spread_d: CellValue32::new(spread_d.spread.var, spread_d.spread.value),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -102,70 +111,107 @@ impl MessageScheduleConfig {
|
|||
let row = get_word_row(word.index) + 3;
|
||||
|
||||
// Assign `a` and copy constraint
|
||||
self.assign_and_constrain(region, || "a", a_5, row + 1, &word.a)?;
|
||||
self.assign_and_constrain(region, || "a", a_5, row + 1, word.a)?;
|
||||
|
||||
// Witness `spread_a`
|
||||
let spread_a = interleave_u16_with_zeros(word.a.value.unwrap() as u16);
|
||||
let spread_a = word
|
||||
.a
|
||||
.value
|
||||
.map(|value| interleave_u16_with_zeros(value as u16));
|
||||
region.assign_advice(
|
||||
|| "spread_a",
|
||||
a_6,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(spread_a as u64)),
|
||||
|| {
|
||||
spread_a
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Split `b` (2-bit chunk) into `b_hi` and `b_lo`
|
||||
let b = word.b.value.unwrap();
|
||||
let (b_lo, b_hi) = bisect_four_bit(b);
|
||||
let spread_b_lo = interleave_u16_with_zeros(b_lo as u16);
|
||||
let spread_b_hi = interleave_u16_with_zeros(b_hi as u16);
|
||||
let b = word.b.value.map(bisect_four_bit);
|
||||
let spread_b_lo = b.map(|b| interleave_u16_with_zeros(b.0 as u16));
|
||||
let spread_b_hi = b.map(|b| interleave_u16_with_zeros(b.1 as u16));
|
||||
|
||||
// Assign `b_hi`, `spread_b_hi`, `b_lo`, `spread_b_lo`
|
||||
region.assign_advice(|| "b_lo", a_3, row - 1, || Ok(F::from_u64(b_lo as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "b_lo",
|
||||
a_3,
|
||||
row - 1,
|
||||
|| {
|
||||
b.map(|(b_lo, _)| F::from_u64(b_lo as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_lo",
|
||||
a_4,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_b_lo as u64)),
|
||||
|| {
|
||||
spread_b_lo
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "b_hi",
|
||||
a_5,
|
||||
row - 1,
|
||||
|| {
|
||||
b.map(|(_, b_hi)| F::from_u64(b_hi as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(|| "b_hi", a_5, row - 1, || Ok(F::from_u64(b_hi as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_hi",
|
||||
a_6,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_b_hi as u64)),
|
||||
|| {
|
||||
spread_b_hi
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `b` and copy constraint
|
||||
self.assign_and_constrain(region, || "b", a_6, row, &word.b)?;
|
||||
self.assign_and_constrain(region, || "b", a_6, row, word.b)?;
|
||||
|
||||
// Assign `spread_c` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_c", a_4, row, &word.spread_c)?;
|
||||
self.assign_and_constrain(region, || "spread_c", a_4, row, word.spread_c)?;
|
||||
|
||||
// Assign `spread_d` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_d", a_5, row, &word.spread_d)?;
|
||||
self.assign_and_constrain(region, || "spread_d", a_5, row, word.spread_d)?;
|
||||
|
||||
// Calculate R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let spread_a = spread_a as u64;
|
||||
let spread_b_lo = spread_b_lo as u64;
|
||||
let spread_b_hi = spread_b_hi as u64;
|
||||
let spread_c = word.spread_c.value.unwrap() as u64;
|
||||
let spread_d = word.spread_d.value.unwrap() as u64;
|
||||
let xor_0: u64 =
|
||||
spread_b_lo + (1 << 4) * spread_b_hi + (1 << 8) * spread_c + (1 << 30) * spread_d;
|
||||
let xor_1: u64 = spread_c
|
||||
+ (1 << 22) * spread_d
|
||||
+ (1 << 50) * spread_a
|
||||
+ (1 << 56) * spread_b_lo
|
||||
+ (1 << 60) * spread_b_hi;
|
||||
let xor_2: u64 = spread_d
|
||||
+ (1 << 28) * spread_a
|
||||
+ (1 << 34) * spread_b_lo
|
||||
+ (1 << 38) * spread_b_hi
|
||||
+ (1 << 42) * spread_c;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
let (r_0_even, r_0_odd, r_1_even, r_1_odd) = if let Some(spread_a) = spread_a {
|
||||
let spread_a = spread_a as u64;
|
||||
let spread_b_lo = spread_b_lo.unwrap() as u64;
|
||||
let spread_b_hi = spread_b_hi.unwrap() as u64;
|
||||
let spread_c = word.spread_c.value.unwrap() as u64;
|
||||
let spread_d = word.spread_d.value.unwrap() as u64;
|
||||
|
||||
let xor_0: u64 =
|
||||
spread_b_lo + (1 << 4) * spread_b_hi + (1 << 8) * spread_c + (1 << 30) * spread_d;
|
||||
let xor_1: u64 = spread_c
|
||||
+ (1 << 22) * spread_d
|
||||
+ (1 << 50) * spread_a
|
||||
+ (1 << 56) * spread_b_lo
|
||||
+ (1 << 60) * spread_b_hi;
|
||||
let xor_2: u64 = spread_d
|
||||
+ (1 << 28) * spread_a
|
||||
+ (1 << 34) * spread_b_lo
|
||||
+ (1 << 38) * spread_b_hi
|
||||
+ (1 << 42) * spread_c;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
|
||||
(Some(r_0_even), Some(r_0_odd), Some(r_1_even), Some(r_1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_sigma_outputs(
|
||||
region,
|
||||
|
|
|
@ -8,12 +8,12 @@ use halo2::{arithmetic::FieldExt, circuit::Region, plonk::Error};
|
|||
pub struct Subregion2Word {
|
||||
index: usize,
|
||||
a: CellValue32,
|
||||
b: CellValue32,
|
||||
b: CellValue16,
|
||||
c: CellValue32,
|
||||
d: CellValue32,
|
||||
d: CellValue16,
|
||||
e: CellValue32,
|
||||
f: CellValue32,
|
||||
g: CellValue32,
|
||||
g: CellValue16,
|
||||
spread_d: CellValue32,
|
||||
spread_g: CellValue32,
|
||||
}
|
||||
|
@ -50,8 +50,7 @@ impl MessageScheduleConfig {
|
|||
sigma_0_output: (CellValue16, CellValue16)|
|
||||
-> Result<Vec<(CellValue16, CellValue16)>, Error> {
|
||||
// Decompose word into (3, 4, 3, 7, 1, 1, 13)-bit chunks
|
||||
let subregion2_word =
|
||||
self.decompose_subregion2_word(region, w[idx].value.unwrap(), idx)?;
|
||||
let subregion2_word = self.decompose_subregion2_word(region, w[idx].value, idx)?;
|
||||
|
||||
// sigma_0 v2 and sigma_1 v2 on subregion2_word
|
||||
lower_sigma_0_v2_results.push(self.lower_sigma_0_v2(region, subregion2_word.clone())?);
|
||||
|
@ -65,14 +64,14 @@ impl MessageScheduleConfig {
|
|||
|| format!("sigma_0(W_{})_lo", new_word_idx - 15),
|
||||
a_6,
|
||||
get_word_row(new_word_idx - 16),
|
||||
&sigma_0_output.0.into(),
|
||||
sigma_0_output.0,
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| format!("sigma_0(W_{})_hi", new_word_idx - 15),
|
||||
a_6,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
&sigma_0_output.1.into(),
|
||||
sigma_0_output.1,
|
||||
)?;
|
||||
|
||||
// Copy sigma_1(W_{i - 2})
|
||||
|
@ -81,14 +80,14 @@ impl MessageScheduleConfig {
|
|||
|| format!("sigma_1(W_{})_lo", new_word_idx - 2),
|
||||
a_7,
|
||||
get_word_row(new_word_idx - 16),
|
||||
&lower_sigma_1_v2_results[new_word_idx - 16].0.into(),
|
||||
lower_sigma_1_v2_results[new_word_idx - 16].0,
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| format!("sigma_1(W_{})_hi", new_word_idx - 2),
|
||||
a_7,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
&lower_sigma_1_v2_results[new_word_idx - 16].1.into(),
|
||||
lower_sigma_1_v2_results[new_word_idx - 16].1,
|
||||
)?;
|
||||
|
||||
// Copy W_{i - 7}
|
||||
|
@ -97,48 +96,55 @@ impl MessageScheduleConfig {
|
|||
|| format!("W_{}_lo", new_word_idx - 7),
|
||||
a_8,
|
||||
get_word_row(new_word_idx - 16),
|
||||
&w_halves[new_word_idx - 7].0.into(),
|
||||
w_halves[new_word_idx - 7].0,
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| format!("W_{}_hi", new_word_idx - 7),
|
||||
a_8,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
&w_halves[new_word_idx - 7].1.into(),
|
||||
w_halves[new_word_idx - 7].1,
|
||||
)?;
|
||||
|
||||
// Calculate W_i, carry_i
|
||||
let word_lo: u32 = lower_sigma_1_v2_results[new_word_idx - 16].0.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 7].0.value.unwrap() as u32
|
||||
+ sigma_0_output.0.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 16].0.value.unwrap() as u32;
|
||||
let word_hi: u32 = lower_sigma_1_v2_results[new_word_idx - 16].1.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 7].1.value.unwrap() as u32
|
||||
+ sigma_0_output.1.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 16].1.value.unwrap() as u32;
|
||||
|
||||
let word: u64 = word_lo as u64 + (1 << 16) * (word_hi as u64);
|
||||
let carry = word >> 32;
|
||||
let word = word as u32;
|
||||
let (word, carry) = sum_with_carry(vec![
|
||||
(
|
||||
lower_sigma_1_v2_results[new_word_idx - 16].0.value,
|
||||
lower_sigma_1_v2_results[new_word_idx - 16].1.value,
|
||||
),
|
||||
(
|
||||
w_halves[new_word_idx - 7].0.value,
|
||||
w_halves[new_word_idx - 7].1.value,
|
||||
),
|
||||
(sigma_0_output.0.value, sigma_0_output.1.value),
|
||||
(
|
||||
w_halves[new_word_idx - 16].0.value,
|
||||
w_halves[new_word_idx - 16].1.value,
|
||||
),
|
||||
]);
|
||||
|
||||
// Assign W_i, carry_i
|
||||
region.assign_advice(
|
||||
|| format!("W_{}", new_word_idx),
|
||||
a_5,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
|| Ok(F::from_u64(word as u64)),
|
||||
|| {
|
||||
word.map(|word| F::from_u64(word as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| format!("carry_{}", new_word_idx),
|
||||
a_9,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
|| Ok(F::from_u64(carry as u64)),
|
||||
|| {
|
||||
carry
|
||||
.map(|carry| F::from_u64(carry as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
let (var, halves) = self.assign_word_and_halves(region, word, new_word_idx)?;
|
||||
w.push(MessageWord {
|
||||
var,
|
||||
value: Some(word),
|
||||
});
|
||||
w.push(MessageWord { var, value: word });
|
||||
w_halves.push(halves);
|
||||
|
||||
Ok(lower_sigma_0_v2_results.clone())
|
||||
|
@ -164,7 +170,7 @@ impl MessageScheduleConfig {
|
|||
fn decompose_subregion2_word<F: FieldExt>(
|
||||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
word: u32,
|
||||
word: Option<u32>,
|
||||
index: usize,
|
||||
) -> Result<Subregion2Word, Error> {
|
||||
let row = get_word_row(index);
|
||||
|
@ -173,43 +179,80 @@ impl MessageScheduleConfig {
|
|||
let a_3 = self.extras[0];
|
||||
let a_4 = self.extras[1];
|
||||
|
||||
let pieces = chop_u32(word, &[3, 4, 3, 7, 1, 1, 13]);
|
||||
let pieces = word.map(|word| chop_u32(word, &[3, 4, 3, 7, 1, 1, 13]));
|
||||
let pieces = transpose_option_vec(pieces, 7);
|
||||
|
||||
// Assign `a` (3-bit piece)
|
||||
let a = region.assign_advice(|| "a", a_3, row - 1, || Ok(F::from_u64(pieces[0] as u64)))?;
|
||||
let a = region.assign_advice(
|
||||
|| "a",
|
||||
a_3,
|
||||
row - 1,
|
||||
|| {
|
||||
pieces[0]
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `b` (4-bit piece) lookup
|
||||
let spread_b = SpreadWord::new(pieces[1] as u16);
|
||||
let spread_b = SpreadWord::opt_new(pieces[1].map(|value| value as u16));
|
||||
let spread_b = SpreadVar::with_lookup(region, &self.lookup, row + 1, spread_b)?;
|
||||
|
||||
// Assign `c` (3-bit piece)
|
||||
let c = region.assign_advice(|| "c", a_4, row - 1, || Ok(F::from_u64(pieces[2] as u64)))?;
|
||||
let c = region.assign_advice(
|
||||
|| "c",
|
||||
a_4,
|
||||
row - 1,
|
||||
|| {
|
||||
pieces[2]
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `d` (7-bit piece) lookup
|
||||
let spread_d = SpreadWord::new(pieces[3] as u16);
|
||||
let spread_d = SpreadWord::opt_new(pieces[3].map(|value| value as u16));
|
||||
let spread_d = SpreadVar::with_lookup(region, &self.lookup, row, spread_d)?;
|
||||
|
||||
// Assign `e` (1-bit piece)
|
||||
let e = region.assign_advice(|| "e", a_3, row + 1, || Ok(F::from_u64(pieces[4] as u64)))?;
|
||||
let e = region.assign_advice(
|
||||
|| "e",
|
||||
a_3,
|
||||
row + 1,
|
||||
|| {
|
||||
pieces[4]
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `f` (1-bit piece)
|
||||
let f = region.assign_advice(|| "f", a_4, row + 1, || Ok(F::from_u64(pieces[5] as u64)))?;
|
||||
let f = region.assign_advice(
|
||||
|| "f",
|
||||
a_4,
|
||||
row + 1,
|
||||
|| {
|
||||
pieces[5]
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `g` (13-bit piece) lookup
|
||||
let spread_g = SpreadWord::new(pieces[6] as u16);
|
||||
let spread_g = SpreadWord::opt_new(pieces[6].map(|value| value as u16));
|
||||
let spread_g = SpreadVar::with_lookup(region, &self.lookup, row - 1, spread_g)?;
|
||||
|
||||
Ok(Subregion2Word {
|
||||
index,
|
||||
a: CellValue32::new(a, pieces[0]),
|
||||
b: CellValue32::new(spread_b.dense.var, spread_b.dense.value.unwrap().into()),
|
||||
b: CellValue16::new(spread_b.dense.var, spread_b.dense.value),
|
||||
c: CellValue32::new(c, pieces[2]),
|
||||
d: CellValue32::new(spread_d.dense.var, spread_d.dense.value.unwrap().into()),
|
||||
d: CellValue16::new(spread_d.dense.var, spread_d.dense.value),
|
||||
e: CellValue32::new(e, pieces[4]),
|
||||
f: CellValue32::new(f, pieces[5]),
|
||||
g: CellValue32::new(spread_g.dense.var, spread_g.dense.value.unwrap().into()),
|
||||
spread_d: CellValue32::new(spread_d.spread.var, spread_d.spread.value.unwrap()),
|
||||
spread_g: CellValue32::new(spread_g.spread.var, spread_g.spread.value.unwrap()),
|
||||
g: CellValue16::new(spread_g.dense.var, spread_g.dense.value),
|
||||
spread_d: CellValue32::new(spread_d.spread.var, spread_d.spread.value),
|
||||
spread_g: CellValue32::new(spread_g.spread.var, spread_g.spread.value),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -219,7 +262,7 @@ impl MessageScheduleConfig {
|
|||
region: &mut Region<'_, F>,
|
||||
row: usize,
|
||||
subregion2_word: Subregion2Word,
|
||||
) -> Result<(u64, u64, u64, u64, u64, u64, u64, u64), Error> {
|
||||
) -> Result<[Option<u32>; 8], Error> {
|
||||
let a_3 = self.extras[0];
|
||||
let a_4 = self.extras[1];
|
||||
let a_5 = self.message_schedule;
|
||||
|
@ -227,76 +270,113 @@ impl MessageScheduleConfig {
|
|||
let a_7 = self.extras[3];
|
||||
|
||||
// Assign `a` and copy constraint
|
||||
self.assign_and_constrain(region, || "a", a_3, row + 1, &subregion2_word.a)?;
|
||||
self.assign_and_constrain(region, || "a", a_3, row + 1, subregion2_word.a)?;
|
||||
|
||||
// Witness `spread_a`
|
||||
let spread_a = interleave_u16_with_zeros(subregion2_word.a.value.unwrap() as u16);
|
||||
let spread_a = subregion2_word
|
||||
.a
|
||||
.value
|
||||
.map(|value| interleave_u16_with_zeros(value as u16));
|
||||
region.assign_advice(
|
||||
|| "spread_a",
|
||||
a_4,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(spread_a as u64)),
|
||||
|| {
|
||||
spread_a
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Split `b` (2-bit chunk) into `b_hi` and `b_lo`
|
||||
let b = subregion2_word.b.value.unwrap();
|
||||
let (b_lo, b_hi) = bisect_four_bit(b);
|
||||
let spread_b_lo = interleave_u16_with_zeros(b_lo as u16);
|
||||
let spread_b_hi = interleave_u16_with_zeros(b_hi as u16);
|
||||
let b = subregion2_word.b.value.map(bisect_four_bit);
|
||||
let spread_b_lo = b.map(|b| interleave_u16_with_zeros(b.0 as u16));
|
||||
let spread_b_hi = b.map(|b| interleave_u16_with_zeros(b.1 as u16));
|
||||
|
||||
// Assign `b_hi`, `spread_b_hi`, `b_lo`, `spread_b_lo`
|
||||
region.assign_advice(|| "b_lo", a_3, row - 1, || Ok(F::from_u64(b_lo as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "b_lo",
|
||||
a_3,
|
||||
row - 1,
|
||||
|| {
|
||||
b.map(|(b_lo, _)| F::from_u64(b_lo as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_lo",
|
||||
a_4,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_b_lo as u64)),
|
||||
|| {
|
||||
spread_b_lo
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "b_hi",
|
||||
a_5,
|
||||
row - 1,
|
||||
|| {
|
||||
b.map(|(_, b_hi)| F::from_u64(b_hi as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(|| "b_hi", a_5, row - 1, || Ok(F::from_u64(b_hi as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_hi",
|
||||
a_6,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_b_hi as u64)),
|
||||
|| {
|
||||
spread_b_hi
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `b` and copy constraint
|
||||
self.assign_and_constrain(region, || "b", a_6, row, &subregion2_word.b)?;
|
||||
self.assign_and_constrain(region, || "b", a_6, row, subregion2_word.b)?;
|
||||
|
||||
// Assign `c` and copy constraint
|
||||
self.assign_and_constrain(region, || "c", a_5, row + 1, &subregion2_word.c)?;
|
||||
self.assign_and_constrain(region, || "c", a_5, row + 1, subregion2_word.c)?;
|
||||
|
||||
// Witness `spread_c`
|
||||
let spread_c = interleave_u16_with_zeros(subregion2_word.c.value.unwrap() as u16);
|
||||
let spread_c = subregion2_word.c.value.map(|value| {
|
||||
let spread = interleave_u16_with_zeros(value as u16);
|
||||
spread as u32
|
||||
});
|
||||
region.assign_advice(
|
||||
|| "spread_c",
|
||||
a_6,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(spread_c as u64)),
|
||||
|| {
|
||||
spread_c
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `spread_d` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_d", a_4, row, &subregion2_word.spread_d)?;
|
||||
self.assign_and_constrain(region, || "spread_d", a_4, row, subregion2_word.spread_d)?;
|
||||
|
||||
// Assign `e` and copy constraint
|
||||
self.assign_and_constrain(region, || "e", a_7, row, &subregion2_word.e)?;
|
||||
self.assign_and_constrain(region, || "e", a_7, row, subregion2_word.e)?;
|
||||
|
||||
// Assign `f` and copy constraint
|
||||
self.assign_and_constrain(region, || "f", a_7, row + 1, &subregion2_word.f)?;
|
||||
self.assign_and_constrain(region, || "f", a_7, row + 1, subregion2_word.f)?;
|
||||
|
||||
// Assign `spread_g` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_g", a_5, row, &subregion2_word.spread_g)?;
|
||||
self.assign_and_constrain(region, || "spread_g", a_5, row, subregion2_word.spread_g)?;
|
||||
|
||||
Ok((
|
||||
spread_a as u64,
|
||||
spread_b_lo as u64,
|
||||
spread_b_hi as u64,
|
||||
spread_c as u64,
|
||||
subregion2_word.spread_d.value.unwrap() as u64,
|
||||
subregion2_word.e.value.unwrap() as u64,
|
||||
subregion2_word.f.value.unwrap() as u64,
|
||||
subregion2_word.spread_g.value.unwrap() as u64,
|
||||
))
|
||||
Ok([
|
||||
spread_a,
|
||||
spread_b_lo,
|
||||
spread_b_hi,
|
||||
spread_c,
|
||||
subregion2_word.spread_d.value,
|
||||
subregion2_word.e.value,
|
||||
subregion2_word.f.value,
|
||||
subregion2_word.spread_g.value,
|
||||
])
|
||||
}
|
||||
|
||||
fn lower_sigma_0_v2<F: FieldExt>(
|
||||
|
@ -308,38 +388,50 @@ impl MessageScheduleConfig {
|
|||
let row = get_word_row(subregion2_word.index) + 3;
|
||||
|
||||
// Get spread pieces
|
||||
let (spread_a, spread_b_lo, spread_b_hi, spread_c, spread_d, e, f, spread_g) =
|
||||
self.assign_lower_sigma_v2_pieces(region, row, subregion2_word)?;
|
||||
let pieces = self.assign_lower_sigma_v2_pieces(region, row, subregion2_word)?;
|
||||
|
||||
// Calculate R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let xor_0 = spread_b_lo
|
||||
+ (1 << 4) * spread_b_hi
|
||||
+ (1 << 8) * spread_c
|
||||
+ (1 << 14) * spread_d
|
||||
+ (1 << 28) * e
|
||||
+ (1 << 30) * f
|
||||
+ (1 << 32) * spread_g;
|
||||
let xor_1 = spread_c
|
||||
+ (1 << 6) * spread_d
|
||||
+ (1 << 20) * e
|
||||
+ (1 << 22) * f
|
||||
+ (1 << 24) * spread_g
|
||||
+ (1 << 50) * spread_a
|
||||
+ (1 << 56) * spread_b_lo
|
||||
+ (1 << 60) * spread_b_hi;
|
||||
let xor_2 = f
|
||||
+ (1 << 2) * spread_g
|
||||
+ (1 << 28) * spread_a
|
||||
+ (1 << 34) * spread_b_lo
|
||||
+ (1 << 38) * spread_b_hi
|
||||
+ (1 << 42) * spread_c
|
||||
+ (1 << 48) * spread_d
|
||||
+ (1 << 62) * e;
|
||||
let (r_0_even, r_0_odd, r_1_even, r_1_odd) = if pieces[0].is_some() {
|
||||
let pieces = pieces
|
||||
.iter()
|
||||
.map(|piece| piece.unwrap() as u64)
|
||||
.collect::<Vec<_>>();
|
||||
let [spread_a, spread_b_lo, spread_b_hi, spread_c, spread_d, e, f, spread_g] = [
|
||||
pieces[0], pieces[1], pieces[2], pieces[3], pieces[4], pieces[5], pieces[6],
|
||||
pieces[7],
|
||||
];
|
||||
let xor_0 = spread_b_lo
|
||||
+ (1 << 4) * spread_b_hi
|
||||
+ (1 << 8) * spread_c
|
||||
+ (1 << 14) * spread_d
|
||||
+ (1 << 28) * e
|
||||
+ (1 << 30) * f
|
||||
+ (1 << 32) * spread_g;
|
||||
let xor_1 = spread_c
|
||||
+ (1 << 6) * spread_d
|
||||
+ (1 << 20) * e
|
||||
+ (1 << 22) * f
|
||||
+ (1 << 24) * spread_g
|
||||
+ (1 << 50) * spread_a
|
||||
+ (1 << 56) * spread_b_lo
|
||||
+ (1 << 60) * spread_b_hi;
|
||||
let xor_2 = f
|
||||
+ (1 << 2) * spread_g
|
||||
+ (1 << 28) * spread_a
|
||||
+ (1 << 34) * spread_b_lo
|
||||
+ (1 << 38) * spread_b_hi
|
||||
+ (1 << 42) * spread_c
|
||||
+ (1 << 48) * spread_d
|
||||
+ (1 << 62) * e;
|
||||
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
(Some(r_0_even), Some(r_0_odd), Some(r_1_even), Some(r_1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_sigma_outputs(
|
||||
region,
|
||||
|
@ -361,34 +453,46 @@ impl MessageScheduleConfig {
|
|||
let a_3 = self.extras[0];
|
||||
let row = get_word_row(subregion2_word.index) + SIGMA_0_V2_ROWS + 3;
|
||||
|
||||
let (spread_a, spread_b_lo, spread_b_hi, spread_c, spread_d, e, f, spread_g) =
|
||||
self.assign_lower_sigma_v2_pieces(region, row, subregion2_word)?;
|
||||
let pieces = self.assign_lower_sigma_v2_pieces(region, row, subregion2_word)?;
|
||||
|
||||
// (3, 4, 3, 7, 1, 1, 13)
|
||||
|
||||
// Calculate R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let xor_0 = spread_d + (1 << 14) * e + (1 << 16) * f + (1 << 18) * spread_g;
|
||||
let xor_1 = e
|
||||
+ (1 << 2) * f
|
||||
+ (1 << 4) * spread_g
|
||||
+ (1 << 30) * spread_a
|
||||
+ (1 << 36) * spread_b_lo
|
||||
+ (1 << 40) * spread_b_hi
|
||||
+ (1 << 44) * spread_c
|
||||
+ (1 << 50) * spread_d;
|
||||
let xor_2 = spread_g
|
||||
+ (1 << 26) * spread_a
|
||||
+ (1 << 32) * spread_b_lo
|
||||
+ (1 << 36) * spread_b_hi
|
||||
+ (1 << 40) * spread_c
|
||||
+ (1 << 46) * spread_d
|
||||
+ (1 << 60) * e
|
||||
+ (1 << 62) * f;
|
||||
let (r_0_even, r_0_odd, r_1_even, r_1_odd) = if pieces[0].is_some() {
|
||||
let pieces = pieces
|
||||
.iter()
|
||||
.map(|piece| piece.unwrap() as u64)
|
||||
.collect::<Vec<_>>();
|
||||
let [spread_a, spread_b_lo, spread_b_hi, spread_c, spread_d, e, f, spread_g] = [
|
||||
pieces[0], pieces[1], pieces[2], pieces[3], pieces[4], pieces[5], pieces[6],
|
||||
pieces[7],
|
||||
];
|
||||
let xor_0 = spread_d + (1 << 14) * e + (1 << 16) * f + (1 << 18) * spread_g;
|
||||
let xor_1 = e
|
||||
+ (1 << 2) * f
|
||||
+ (1 << 4) * spread_g
|
||||
+ (1 << 30) * spread_a
|
||||
+ (1 << 36) * spread_b_lo
|
||||
+ (1 << 40) * spread_b_hi
|
||||
+ (1 << 44) * spread_c
|
||||
+ (1 << 50) * spread_d;
|
||||
let xor_2 = spread_g
|
||||
+ (1 << 26) * spread_a
|
||||
+ (1 << 32) * spread_b_lo
|
||||
+ (1 << 36) * spread_b_hi
|
||||
+ (1 << 40) * spread_c
|
||||
+ (1 << 46) * spread_d
|
||||
+ (1 << 60) * e
|
||||
+ (1 << 62) * f;
|
||||
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
(Some(r_0_even), Some(r_0_odd), Some(r_1_even), Some(r_1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_sigma_outputs(
|
||||
region,
|
||||
|
|
|
@ -7,11 +7,11 @@ use halo2::{arithmetic::FieldExt, circuit::Region, plonk::Error};
|
|||
pub struct Subregion3Word {
|
||||
index: usize,
|
||||
#[allow(dead_code)]
|
||||
a: CellValue32,
|
||||
b: CellValue32,
|
||||
c: CellValue32,
|
||||
a: CellValue16,
|
||||
b: CellValue16,
|
||||
c: CellValue16,
|
||||
#[allow(dead_code)]
|
||||
d: CellValue32,
|
||||
d: CellValue16,
|
||||
spread_a: CellValue32,
|
||||
spread_d: CellValue32,
|
||||
}
|
||||
|
@ -40,8 +40,7 @@ impl MessageScheduleConfig {
|
|||
// The lowest-index words involved will be W_[35..58]
|
||||
let mut new_word = |idx: usize| -> Result<(), Error> {
|
||||
// Decompose word into (10, 7, 2, 13)-bit chunks
|
||||
let subregion3_word =
|
||||
self.decompose_subregion3_word(region, w[idx].value.unwrap(), idx)?;
|
||||
let subregion3_word = self.decompose_subregion3_word(region, w[idx].value, idx)?;
|
||||
|
||||
// sigma_1 on subregion3_word
|
||||
let (r_0_even, r_1_even) = self.lower_sigma_1(region, subregion3_word)?;
|
||||
|
@ -54,14 +53,14 @@ impl MessageScheduleConfig {
|
|||
|| format!("sigma_0(W_{})_lo", new_word_idx - 15),
|
||||
a_6,
|
||||
get_word_row(new_word_idx - 16),
|
||||
&lower_sigma_0_v2_output[idx - 49].0.into(),
|
||||
lower_sigma_0_v2_output[idx - 49].0,
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| format!("sigma_0(W_{})_hi", new_word_idx - 15),
|
||||
a_6,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
&lower_sigma_0_v2_output[idx - 49].1.into(),
|
||||
lower_sigma_0_v2_output[idx - 49].1,
|
||||
)?;
|
||||
|
||||
// Copy sigma_1(W_{i - 2})
|
||||
|
@ -70,14 +69,14 @@ impl MessageScheduleConfig {
|
|||
|| format!("sigma_1(W_{})_lo", new_word_idx - 2),
|
||||
a_7,
|
||||
get_word_row(new_word_idx - 16),
|
||||
&r_0_even.into(),
|
||||
r_0_even,
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| format!("sigma_1(W_{})_hi", new_word_idx - 2),
|
||||
a_7,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
&r_1_even.into(),
|
||||
r_1_even,
|
||||
)?;
|
||||
|
||||
// Copy W_{i - 7}
|
||||
|
@ -86,48 +85,55 @@ impl MessageScheduleConfig {
|
|||
|| format!("W_{}_lo", new_word_idx - 7),
|
||||
a_8,
|
||||
get_word_row(new_word_idx - 16),
|
||||
&w_halves[new_word_idx - 7].0.into(),
|
||||
w_halves[new_word_idx - 7].0,
|
||||
)?;
|
||||
self.assign_and_constrain(
|
||||
region,
|
||||
|| format!("W_{}_hi", new_word_idx - 7),
|
||||
a_8,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
&w_halves[new_word_idx - 7].1.into(),
|
||||
w_halves[new_word_idx - 7].1,
|
||||
)?;
|
||||
|
||||
// Calculate W_i, carry_i
|
||||
let word_lo: u32 = r_0_even.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 7].0.value.unwrap() as u32
|
||||
+ lower_sigma_0_v2_output[idx - 49].0.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 16].0.value.unwrap() as u32;
|
||||
let word_hi: u32 = r_1_even.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 7].1.value.unwrap() as u32
|
||||
+ lower_sigma_0_v2_output[idx - 49].1.value.unwrap() as u32
|
||||
+ w_halves[new_word_idx - 16].1.value.unwrap() as u32;
|
||||
|
||||
let word: u64 = word_lo as u64 + (1 << 16) * (word_hi as u64);
|
||||
let carry = word >> 32;
|
||||
let word = word as u32;
|
||||
let (word, carry) = sum_with_carry(vec![
|
||||
(r_0_even.value, r_1_even.value),
|
||||
(
|
||||
w_halves[new_word_idx - 7].0.value,
|
||||
w_halves[new_word_idx - 7].1.value,
|
||||
),
|
||||
(
|
||||
lower_sigma_0_v2_output[idx - 49].0.value,
|
||||
lower_sigma_0_v2_output[idx - 49].1.value,
|
||||
),
|
||||
(
|
||||
w_halves[new_word_idx - 16].0.value,
|
||||
w_halves[new_word_idx - 16].1.value,
|
||||
),
|
||||
]);
|
||||
|
||||
// Assign W_i, carry_i
|
||||
region.assign_advice(
|
||||
|| format!("W_{}", new_word_idx),
|
||||
a_5,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
|| Ok(F::from_u64(word as u64)),
|
||||
|| {
|
||||
word.map(|word| F::from_u64(word as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| format!("carry_{}", new_word_idx),
|
||||
a_9,
|
||||
get_word_row(new_word_idx - 16) + 1,
|
||||
|| Ok(F::from_u64(carry as u64)),
|
||||
|| {
|
||||
carry
|
||||
.map(|carry| F::from_u64(carry as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
let (var, halves) = self.assign_word_and_halves(region, word, new_word_idx)?;
|
||||
w.push(MessageWord {
|
||||
var,
|
||||
value: Some(word),
|
||||
});
|
||||
w.push(MessageWord { var, value: word });
|
||||
w_halves.push(halves);
|
||||
|
||||
Ok(())
|
||||
|
@ -143,7 +149,7 @@ impl MessageScheduleConfig {
|
|||
fn decompose_subregion3_word<F: FieldExt>(
|
||||
&self,
|
||||
region: &mut Region<'_, F>,
|
||||
word: u32,
|
||||
word: Option<u32>,
|
||||
index: usize,
|
||||
) -> Result<Subregion3Word, Error> {
|
||||
let row = get_word_row(index);
|
||||
|
@ -152,30 +158,56 @@ impl MessageScheduleConfig {
|
|||
let a_3 = self.extras[0];
|
||||
let a_4 = self.extras[1];
|
||||
|
||||
let pieces = chop_u32(word, &[10, 7, 2, 13]);
|
||||
let pieces = transpose_option_vec(
|
||||
word.map(|word| {
|
||||
chop_u32(word, &[10, 7, 2, 13])
|
||||
.into_iter()
|
||||
.map(|piece| piece as u16)
|
||||
.collect()
|
||||
}),
|
||||
4,
|
||||
);
|
||||
|
||||
// Assign `a` (10-bit piece)
|
||||
let spread_a = SpreadWord::new(pieces[0] as u16);
|
||||
let spread_a = pieces[0].map(SpreadWord::new);
|
||||
let spread_a = SpreadVar::with_lookup(region, &self.lookup, row + 1, spread_a)?;
|
||||
|
||||
// Assign `b` (7-bit piece)
|
||||
let b = region.assign_advice(|| "b", a_4, row + 1, || Ok(F::from_u64(pieces[1] as u64)))?;
|
||||
let b = region.assign_advice(
|
||||
|| "b",
|
||||
a_4,
|
||||
row + 1,
|
||||
|| {
|
||||
pieces[1]
|
||||
.map(|piece| F::from_u64(piece as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `c` (2-bit piece)
|
||||
let c = region.assign_advice(|| "c", a_3, row + 1, || Ok(F::from_u64(pieces[2] as u64)))?;
|
||||
let c = region.assign_advice(
|
||||
|| "c",
|
||||
a_3,
|
||||
row + 1,
|
||||
|| {
|
||||
pieces[2]
|
||||
.map(|piece| F::from_u64(piece as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `d` (13-bit piece) lookup
|
||||
let spread_d = SpreadWord::new(pieces[3] as u16);
|
||||
let spread_d = pieces[3].map(SpreadWord::new);
|
||||
let spread_d = SpreadVar::with_lookup(region, &self.lookup, row, spread_d)?;
|
||||
|
||||
Ok(Subregion3Word {
|
||||
index,
|
||||
a: CellValue32::new(spread_a.dense.var, spread_a.dense.value.unwrap().into()),
|
||||
b: CellValue32::new(b, pieces[1]),
|
||||
c: CellValue32::new(c, pieces[2]),
|
||||
d: CellValue32::new(spread_d.dense.var, spread_d.dense.value.unwrap().into()),
|
||||
spread_a: CellValue32::new(spread_a.spread.var, spread_a.spread.value.unwrap()),
|
||||
spread_d: CellValue32::new(spread_d.spread.var, spread_d.spread.value.unwrap()),
|
||||
a: CellValue16::new(spread_a.dense.var, spread_a.dense.value),
|
||||
b: CellValue16::new(b, pieces[1]),
|
||||
c: CellValue16::new(c, pieces[2]),
|
||||
d: CellValue16::new(spread_d.dense.var, spread_d.dense.value),
|
||||
spread_a: CellValue32::new(spread_a.spread.var, spread_a.spread.value),
|
||||
spread_d: CellValue32::new(spread_d.spread.var, spread_d.spread.value),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -192,86 +224,144 @@ impl MessageScheduleConfig {
|
|||
let row = get_word_row(word.index) + 3;
|
||||
|
||||
// Assign `spread_a` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_a", a_4, row, &word.spread_a)?;
|
||||
self.assign_and_constrain(region, || "spread_a", a_4, row, word.spread_a)?;
|
||||
|
||||
// Split `b` (7-bit chunk) into (2,2,3)-bit `b_lo`, `b_mid` and `b_hi`
|
||||
let b = word.b.value.unwrap();
|
||||
let b_hi = (b & 0b1110000) >> 4;
|
||||
let (b_lo, b_mid) = bisect_four_bit(b & 0b1111);
|
||||
let spread_b_lo = interleave_u16_with_zeros(b_lo as u16);
|
||||
let spread_b_mid = interleave_u16_with_zeros(b_mid as u16);
|
||||
let spread_b_hi = interleave_u16_with_zeros(b_hi as u16);
|
||||
let (b_lo, b_mid, b_hi) = {
|
||||
let b_hi = word.b.value.map(|b| (b & 0b1110000) >> 4);
|
||||
let (b_lo, b_mid) = {
|
||||
let b_lo_mid = word.b.value.map(|b| bisect_four_bit(b & 0b1111));
|
||||
(b_lo_mid.map(|(lo, _)| lo), b_lo_mid.map(|(_, mid)| mid))
|
||||
};
|
||||
(b_lo, b_mid, b_hi)
|
||||
};
|
||||
let (spread_b_lo, spread_b_mid, spread_b_hi) = {
|
||||
let spread_b_lo = b_lo.map(|b_lo| interleave_u16_with_zeros(b_lo as u16));
|
||||
let spread_b_mid = b_mid.map(|b_mid| interleave_u16_with_zeros(b_mid as u16));
|
||||
let spread_b_hi = b_hi.map(|b_hi| interleave_u16_with_zeros(b_hi as u16));
|
||||
|
||||
(spread_b_lo, spread_b_mid, spread_b_hi)
|
||||
};
|
||||
|
||||
// Assign `b_lo`, `spread_b_lo`, `b_mid`, `spread_b_mid`, `b_hi`, `spread_b_hi`
|
||||
region.assign_advice(|| "b_lo", a_3, row - 1, || Ok(F::from_u64(b_lo as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "b_lo",
|
||||
a_3,
|
||||
row - 1,
|
||||
|| {
|
||||
b_lo.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_lo",
|
||||
a_4,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_b_lo as u64)),
|
||||
|| {
|
||||
spread_b_lo
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "b_mid",
|
||||
a_5,
|
||||
row - 1,
|
||||
|| {
|
||||
b_mid
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(|| "b_mid", a_5, row - 1, || Ok(F::from_u64(b_mid as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_mid",
|
||||
a_6,
|
||||
row - 1,
|
||||
|| Ok(F::from_u64(spread_b_mid as u64)),
|
||||
|| {
|
||||
spread_b_mid
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(
|
||||
|| "b_hi",
|
||||
a_5,
|
||||
row + 1,
|
||||
|| {
|
||||
b_hi.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
region.assign_advice(|| "b_hi", a_5, row + 1, || Ok(F::from_u64(b_hi as u64)))?;
|
||||
region.assign_advice(
|
||||
|| "spread_b_hi",
|
||||
a_6,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(spread_b_hi as u64)),
|
||||
|| {
|
||||
spread_b_hi
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `b` and copy constraint
|
||||
self.assign_and_constrain(region, || "b", a_6, row, &word.b)?;
|
||||
self.assign_and_constrain(region, || "b", a_6, row, word.b)?;
|
||||
|
||||
// Assign `c` and copy constraint
|
||||
self.assign_and_constrain(region, || "c", a_3, row + 1, &word.c)?;
|
||||
self.assign_and_constrain(region, || "c", a_3, row + 1, word.c)?;
|
||||
|
||||
// Witness `spread_c`
|
||||
let spread_c = interleave_u16_with_zeros(word.c.value.unwrap() as u16);
|
||||
let spread_c = word
|
||||
.c
|
||||
.value
|
||||
.map(|value| interleave_u16_with_zeros(value as u16));
|
||||
region.assign_advice(
|
||||
|| "spread_c",
|
||||
a_4,
|
||||
row + 1,
|
||||
|| Ok(F::from_u64(spread_c as u64)),
|
||||
|| {
|
||||
spread_c
|
||||
.map(|value| F::from_u64(value as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
// Assign `spread_d` and copy constraint
|
||||
self.assign_and_constrain(region, || "spread_d", a_5, row, &word.spread_d)?;
|
||||
self.assign_and_constrain(region, || "spread_d", a_5, row, word.spread_d)?;
|
||||
|
||||
// (10, 7, 2, 13)
|
||||
// Calculate R_0^{even}, R_0^{odd}, R_1^{even}, R_1^{odd}
|
||||
let spread_a = word.spread_a.value.unwrap() as u64;
|
||||
let spread_b_lo = spread_b_lo as u64;
|
||||
let spread_b_mid = spread_b_mid as u64;
|
||||
let spread_b_hi = spread_b_hi as u64;
|
||||
let spread_c = spread_c as u64;
|
||||
let spread_d = word.spread_d.value.unwrap() as u64;
|
||||
let xor_0 = spread_b_lo
|
||||
+ (1 << 4) * spread_b_mid
|
||||
+ (1 << 8) * spread_b_hi
|
||||
+ (1 << 14) * spread_c
|
||||
+ (1 << 18) * spread_d;
|
||||
let xor_1 = spread_c
|
||||
+ (1 << 4) * spread_d
|
||||
+ (1 << 30) * spread_a
|
||||
+ (1 << 50) * spread_b_lo
|
||||
+ (1 << 54) * spread_b_mid
|
||||
+ (1 << 58) * spread_b_hi;
|
||||
let xor_2 = spread_d
|
||||
+ (1 << 26) * spread_a
|
||||
+ (1 << 46) * spread_b_lo
|
||||
+ (1 << 50) * spread_b_mid
|
||||
+ (1 << 54) * spread_b_hi
|
||||
+ (1 << 60) * spread_c;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
let (r_0_even, r_0_odd, r_1_even, r_1_odd) = if word.spread_a.value.is_some() {
|
||||
let spread_a = word.spread_a.value.unwrap() as u64;
|
||||
let spread_b_lo = spread_b_lo.unwrap() as u64;
|
||||
let spread_b_mid = spread_b_mid.unwrap() as u64;
|
||||
let spread_b_hi = spread_b_hi.unwrap() as u64;
|
||||
let spread_c = spread_c.unwrap() as u64;
|
||||
let spread_d = word.spread_d.value.unwrap() as u64;
|
||||
let xor_0 = spread_b_lo
|
||||
+ (1 << 4) * spread_b_mid
|
||||
+ (1 << 8) * spread_b_hi
|
||||
+ (1 << 14) * spread_c
|
||||
+ (1 << 18) * spread_d;
|
||||
let xor_1 = spread_c
|
||||
+ (1 << 4) * spread_d
|
||||
+ (1 << 30) * spread_a
|
||||
+ (1 << 50) * spread_b_lo
|
||||
+ (1 << 54) * spread_b_mid
|
||||
+ (1 << 58) * spread_b_hi;
|
||||
let xor_2 = spread_d
|
||||
+ (1 << 26) * spread_a
|
||||
+ (1 << 46) * spread_b_lo
|
||||
+ (1 << 50) * spread_b_mid
|
||||
+ (1 << 54) * spread_b_hi
|
||||
+ (1 << 60) * spread_c;
|
||||
let r = xor_0 + xor_1 + xor_2;
|
||||
let r_pieces = chop_u64(r, &[32, 32]); // r_0, r_1
|
||||
let (r_0_even, r_0_odd) = get_even_and_odd_bits_u32(r_pieces[0] as u32);
|
||||
let (r_1_even, r_1_odd) = get_even_and_odd_bits_u32(r_pieces[1] as u32);
|
||||
(Some(r_0_even), Some(r_0_odd), Some(r_1_even), Some(r_1_odd))
|
||||
} else {
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
self.assign_sigma_outputs(
|
||||
region,
|
||||
|
|
|
@ -23,12 +23,16 @@ impl SpreadWord {
|
|||
spread: interleave_u16_with_zeros(word),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn opt_new(word: Option<u16>) -> Option<Self> {
|
||||
word.map(SpreadWord::new)
|
||||
}
|
||||
}
|
||||
|
||||
/// A variable stored in advice columns corresponding to a row of [`SpreadTableConfig`].
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(super) struct SpreadVar {
|
||||
pub tag: u8,
|
||||
pub tag: Option<u8>,
|
||||
pub dense: CellValue16,
|
||||
pub spread: CellValue32,
|
||||
}
|
||||
|
@ -38,12 +42,22 @@ impl SpreadVar {
|
|||
region: &mut Region<'_, F>,
|
||||
cols: &SpreadInputs,
|
||||
row: usize,
|
||||
word: SpreadWord,
|
||||
word: Option<SpreadWord>,
|
||||
) -> Result<Self, Error> {
|
||||
let tag = word.tag;
|
||||
let dense_val = Some(word.dense);
|
||||
let spread_val = Some(word.spread);
|
||||
region.assign_advice(|| "tag", cols.tag, row, || Ok(F::from_u64(tag as u64)))?;
|
||||
let tag = word.map(|word| word.tag);
|
||||
let dense_val = word.map(|word| word.dense);
|
||||
let spread_val = word.map(|word| word.spread);
|
||||
|
||||
region.assign_advice(
|
||||
|| "tag",
|
||||
cols.tag,
|
||||
row,
|
||||
|| {
|
||||
tag.map(|tag| F::from_u64(tag as u64))
|
||||
.ok_or(Error::SynthesisError)
|
||||
},
|
||||
)?;
|
||||
|
||||
let dense_var = region.assign_advice(
|
||||
|| "dense",
|
||||
cols.dense,
|
||||
|
@ -67,8 +81,8 @@ impl SpreadVar {
|
|||
|
||||
Ok(SpreadVar {
|
||||
tag,
|
||||
dense: CellValue16::new(dense_var, dense_val.unwrap()),
|
||||
spread: CellValue32::new(spread_var, spread_val.unwrap()),
|
||||
dense: CellValue16::new(dense_var, dense_val),
|
||||
spread: CellValue32::new(spread_var, spread_val),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -78,11 +92,11 @@ impl SpreadVar {
|
|||
dense_row: usize,
|
||||
spread_col: Column<Advice>,
|
||||
spread_row: usize,
|
||||
word: SpreadWord,
|
||||
word: Option<SpreadWord>,
|
||||
) -> Result<Self, Error> {
|
||||
let tag = word.tag;
|
||||
let dense_val = Some(word.dense);
|
||||
let spread_val = Some(word.spread);
|
||||
let tag = word.map(|word| word.tag);
|
||||
let dense_val = word.map(|word| word.dense);
|
||||
let spread_val = word.map(|word| word.spread);
|
||||
let dense_var = region.assign_advice(
|
||||
|| "dense",
|
||||
dense_col,
|
||||
|
@ -106,8 +120,8 @@ impl SpreadVar {
|
|||
|
||||
Ok(SpreadVar {
|
||||
tag,
|
||||
dense: CellValue16::new(dense_var, dense_val.unwrap()),
|
||||
spread: CellValue32::new(spread_var, spread_val.unwrap()),
|
||||
dense: CellValue16::new(dense_var, dense_val),
|
||||
spread: CellValue32::new(spread_var, spread_val),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,9 +87,38 @@ pub fn get_even_and_odd_bits_u32(word: u32) -> (u16, u16) {
|
|||
}
|
||||
|
||||
// Split 4-bit value into 2-bit lo and hi halves
|
||||
pub fn bisect_four_bit(word: u32) -> (u32, u32) {
|
||||
assert!(word < 16); // 4-bit range-check
|
||||
pub fn bisect_four_bit(word: impl Into<u32>) -> (u32, u32) {
|
||||
let word: u32 = word.into();
|
||||
assert!(word < (1 << 4)); // 4-bit range-check
|
||||
let word_hi = (word & 0b1100) >> 2;
|
||||
let word_lo = word & 0b0011;
|
||||
(word_lo, word_hi)
|
||||
}
|
||||
|
||||
/// Helper function to transpose an Option<Vec<F>> to a Vec<Option<F>>.
|
||||
/// The length of the vector must be `len`.
|
||||
pub fn transpose_option_vec<F: Copy>(vec: Option<Vec<F>>, len: usize) -> Vec<Option<F>> {
|
||||
if let Some(vec) = vec {
|
||||
vec.into_iter().map(Some).collect()
|
||||
} else {
|
||||
vec![None; len]
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a vector of words as vec![(lo: u16, hi: u16)], returns their sum: u32, along
|
||||
/// with a carry bit.
|
||||
pub fn sum_with_carry(words: Vec<(Option<u16>, Option<u16>)>) -> (Option<u32>, Option<u64>) {
|
||||
let words_lo: Option<Vec<u64>> = words.iter().map(|(lo, _)| lo.map(|lo| lo as u64)).collect();
|
||||
let words_hi: Option<Vec<u64>> = words.iter().map(|(_, hi)| hi.map(|hi| hi as u64)).collect();
|
||||
|
||||
let sum: Option<u64> = {
|
||||
let sum_lo: Option<u64> = words_lo.map(|vec| vec.iter().sum());
|
||||
let sum_hi: Option<u64> = words_hi.map(|vec| vec.iter().sum());
|
||||
sum_lo.zip(sum_hi).map(|(lo, hi)| lo + (1 << 16) * hi)
|
||||
};
|
||||
|
||||
let carry = sum.map(|sum| (sum >> 32) as u64);
|
||||
let sum = sum.map(|sum| sum as u32);
|
||||
|
||||
(sum, carry)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue