diff --git a/src/gadget/sha256/table16.rs b/src/gadget/sha256/table16.rs index 433ec83..df66cca 100644 --- a/src/gadget/sha256/table16.rs +++ b/src/gadget/sha256/table16.rs @@ -22,7 +22,7 @@ const ROUNDS: usize = 64; const STATE: usize = 8; #[allow(clippy::unreadable_literal)] -const ROUND_CONSTANTS: [u32; ROUNDS] = [ +pub(crate) const ROUND_CONSTANTS: [u32; ROUNDS] = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, diff --git a/src/gadget/sha256/table16/compression.rs b/src/gadget/sha256/table16/compression.rs index 7bb8bde..7547bdd 100644 --- a/src/gadget/sha256/table16/compression.rs +++ b/src/gadget/sha256/table16/compression.rs @@ -13,7 +13,7 @@ mod compression_gates; mod compression_util; // mod subregion_digest; mod subregion_initial; -// mod subregion_main; +mod subregion_main; use compression_gates::CompressionGate; @@ -717,7 +717,18 @@ impl Compression { w_halves: [(CellValue16, CellValue16); ROUNDS], ) -> Result { let mut state = State::empty_state(); - todo!() + layouter.assign_region( + || "compress", + |mut region| { + state = initialized_state.clone(); + for idx in 0..64 { + state = + self.assign_round(&mut region, idx, state.clone(), w_halves[idx as usize])?; + } + Ok(()) + }, + )?; + Ok(state) } /// After the final round, convert the state into the final digest. diff --git a/src/gadget/sha256/table16/compression/subregion_main.rs b/src/gadget/sha256/table16/compression/subregion_main.rs new file mode 100644 index 0000000..30b5925 --- /dev/null +++ b/src/gadget/sha256/table16/compression/subregion_main.rs @@ -0,0 +1,137 @@ +use super::super::{ + CellValue16, RoundWordA, RoundWordE, StateWord, Table16Assignment, Table16Chip, ROUND_CONSTANTS, +}; +use super::{compression_util::*, Compression, State}; +use crate::{arithmetic::FieldExt, circuit::Region, plonk::Error}; + +impl Compression { + pub fn assign_round( + &self, + region: &mut Region<'_, Table16Chip>, + idx: i32, + state: State, + schedule_word: (CellValue16, CellValue16), + ) -> Result { + let a_3 = self.extras[0]; + let a_4 = self.extras[1]; + let a_7 = self.extras[3]; + + let (a, b, c, d, e, f, g, h) = match_state(state); + + // s_upper_sigma_1(E) + let sigma_1 = self.assign_upper_sigma_1(region, idx, e.pieces.unwrap())?; + + // Ch(E, F, G) + let ch = self.assign_ch(region, idx, e.spread_halves.unwrap(), f.spread_halves)?; + let ch_neg = self.assign_ch_neg(region, idx, e.spread_halves.unwrap(), g.spread_halves)?; + + // s_upper_sigma_0(A) + let sigma_0 = self.assign_upper_sigma_0(region, idx, a.pieces.unwrap())?; + + // Maj(A, B, C) + let maj = self.assign_maj( + region, + idx, + a.spread_halves.unwrap(), + b.spread_halves, + c.spread_halves, + )?; + + // H' = H + Ch(E, F, G) + s_upper_sigma_1(E) + K + W + let h_prime = self.assign_h_prime( + region, + idx, + h.dense_halves, + ch, + ch_neg, + sigma_1, + ROUND_CONSTANTS[idx as usize], + schedule_word, + )?; + + // E_new = H' + D + let e_new_dense = self.assign_e_new(region, idx, d.dense_halves, h_prime)?; + let e_new_val = val_from_dense_halves(e_new_dense); + + // A_new = H' + Maj(A, B, C) + sigma_0(A) + let a_new_dense = self.assign_a_new(region, idx, maj, sigma_0, h_prime)?; + let a_new_val = val_from_dense_halves(a_new_dense); + + 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.perm, + )?; + self.assign_and_constrain( + region, + || "a_new_hi", + a_7, + a_new_row + 1, + &a_new_dense.1.into(), + &self.perm, + )?; + + // 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.perm, + )?; + self.assign_and_constrain( + region, + || "e_new_hi", + a_7, + e_new_row + 1, + &e_new_dense.1.into(), + &self.perm, + )?; + + // Decompose A into (2, 11, 9, 10)-bit chunks + let a_new = self.decompose_a(region, idx + 1, a_new_val)?; + + // Decompose E into (6, 5, 14, 7)-bit chunks + let e_new = self.decompose_e(region, idx + 1, e_new_val)?; + + Ok(State::new( + StateWord::A(a_new), + StateWord::B(a.into()), + StateWord::C(b), + StateWord::D(c.into()), + StateWord::E(e_new), + StateWord::F(e.into()), + StateWord::G(f), + StateWord::H(g.into()), + )) + } else { + let abcd_row = get_digest_abcd_row(); + let efgh_row = get_digest_efgh_row(); + + let a_final = + self.assign_word_halves_dense(region, abcd_row, a_3, abcd_row, a_4, a_new_val)?; + + let e_final = + self.assign_word_halves_dense(region, efgh_row, a_3, efgh_row, a_4, e_new_val)?; + + Ok(State::new( + StateWord::A(RoundWordA::new_dense(a_final)), + StateWord::B(a.into()), + StateWord::C(b), + StateWord::D(c.into()), + StateWord::E(RoundWordE::new_dense(e_final)), + StateWord::F(e.into()), + StateWord::G(f), + StateWord::H(g.into()), + )) + } + } +}