From 6ac114092d79c7695fb9f6d80c4d18178d986b33 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Wed, 29 Nov 2023 22:01:08 +0800 Subject: [PATCH 1/2] upgrade sha256 --- halo2_gadgets/src/lib.rs | 4 +- halo2_gadgets/src/sha256/table16.rs | 183 +++++++--- .../src/sha256/table16/compression.rs | 345 ++++++++++-------- .../table16/compression/compression_gates.rs | 37 +- .../table16/compression/compression_util.rs | 225 ++++++------ .../table16/compression/subregion_digest.rs | 254 ++++++++----- .../table16/compression/subregion_initial.rs | 74 ++-- .../table16/compression/subregion_main.rs | 33 +- .../src/sha256/table16/message_schedule.rs | 44 ++- .../table16/message_schedule/schedule_util.rs | 46 ++- .../table16/message_schedule/subregion1.rs | 73 ++-- .../table16/message_schedule/subregion2.rs | 280 +++++++------- .../table16/message_schedule/subregion3.rs | 63 ++-- .../src/sha256/table16/spread_table.rs | 39 +- halo2_gadgets/src/sha256/table16/util.rs | 2 +- 15 files changed, 969 insertions(+), 733 deletions(-) diff --git a/halo2_gadgets/src/lib.rs b/halo2_gadgets/src/lib.rs index 8d4d4292b0..446b16c5f6 100644 --- a/halo2_gadgets/src/lib.rs +++ b/halo2_gadgets/src/lib.rs @@ -25,8 +25,8 @@ pub mod ecc; pub mod poseidon; -#[cfg(feature = "unstable")] -#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] +//#[cfg(feature = "unstable")] +//#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] pub mod sha256; pub mod sinsemilla; pub mod utilities; diff --git a/halo2_gadgets/src/sha256/table16.rs b/halo2_gadgets/src/sha256/table16.rs index c4919158bc..33fb54f1a3 100644 --- a/halo2_gadgets/src/sha256/table16.rs +++ b/halo2_gadgets/src/sha256/table16.rs @@ -1,12 +1,9 @@ -use std::convert::TryInto; -use std::marker::PhantomData; - -use super::Sha256Instructions; +use halo2_proofs::arithmetic::FieldExt as Field; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Region, Value}, plonk::{Advice, Any, Assigned, Column, ConstraintSystem, Error}, }; -use halo2curves::pasta::pallas; +use std::convert::TryInto; mod compression; mod gates; @@ -81,10 +78,10 @@ impl From<&Bits> for [bool; LEN] { } } -impl From<&Bits> for Assigned { - fn from(bits: &Bits) -> Assigned { +impl From<&Bits> for Assigned { + fn from(bits: &Bits) -> Assigned { assert!(LEN <= 64); - pallas::Base::from(lebs2ip(&bits.0)).into() + F::from(lebs2ip(&bits.0)).into() } } @@ -112,20 +109,21 @@ impl From for Bits<32> { } } +/// Assigned bits #[derive(Clone, Debug)] -pub struct AssignedBits(AssignedCell, pallas::Base>); +pub struct AssignedBits(pub AssignedCell, F>); -impl std::ops::Deref for AssignedBits { - type Target = AssignedCell, pallas::Base>; +impl std::ops::Deref for AssignedBits { + type Target = AssignedCell, F>; fn deref(&self) -> &Self::Target { &self.0 } } -impl AssignedBits { +impl AssignedBits { fn assign_bits + std::fmt::Debug + Clone>( - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, annotation: A, column: impl Into>, offset: usize, @@ -157,13 +155,13 @@ impl AssignedBits { } } -impl AssignedBits<16> { +impl AssignedBits { fn value_u16(&self) -> Value { self.value().map(|v| v.into()) } fn assign( - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, annotation: A, column: impl Into>, offset: usize, @@ -192,13 +190,13 @@ impl AssignedBits<16> { } } -impl AssignedBits<32> { +impl AssignedBits { fn value_u32(&self) -> Value { self.value().map(|v| v.into()) } fn assign( - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, annotation: A, column: impl Into>, offset: usize, @@ -235,14 +233,53 @@ pub struct Table16Config { compression: CompressionConfig, } +impl Table16Config { + pub(crate) fn initialize( + &self, + layouter: &mut impl Layouter, + init_state_assigned: [RoundWordDense; STATE], + ) -> Result, Error> { + self.compression.initialize(layouter, init_state_assigned) + } + + pub(crate) fn compress( + &self, + layouter: &mut impl Layouter, + initialized_state: State, + w_halves: [(AssignedBits, AssignedBits); ROUNDS], + ) -> Result, Error> { + self.compression + .compress(layouter, initialized_state, w_halves) + } + + pub(crate) fn digest( + &self, + layouter: &mut impl Layouter, + final_state: State, + initialized_state: State, + ) -> Result<[RoundWordDense; STATE], Error> { + self.compression + .digest(layouter, final_state, initialized_state) + } + + #[allow(clippy::type_complexity)] + pub(crate) fn message_process( + &self, + layouter: &mut impl Layouter, + input: [BlockWord; super::BLOCK_SIZE], + ) -> Result<[(AssignedBits, AssignedBits); ROUNDS], Error> { + let (_, w_halves) = self.message_schedule.process(layouter, input)?; + Ok(w_halves) + } +} + /// A chip that implements SHA-256 with a maximum lookup table size of $2^16$. #[derive(Clone, Debug)] pub struct Table16Chip { config: Table16Config, - _marker: PhantomData, } -impl Chip for Table16Chip { +impl Chip for Table16Chip { type Config = Table16Config; type Loaded = (); @@ -257,17 +294,12 @@ impl Chip for Table16Chip { impl Table16Chip { /// Reconstructs this chip from the given config. - pub fn construct(config: >::Config) -> Self { - Self { - config, - _marker: PhantomData, - } + pub fn construct(config: >::Config) -> Self { + Self { config } } /// Configures a circuit to include this chip. - pub fn configure( - meta: &mut ConstraintSystem, - ) -> >::Config { + pub fn configure(meta: &mut ConstraintSystem) -> >::Config { // Columns required by this chip: let message_schedule = meta.advice_column(); let extras = [ @@ -318,69 +350,114 @@ impl Table16Chip { } /// Loads the lookup table required by this chip into the circuit. - pub fn load( + pub fn load( config: Table16Config, - layouter: &mut impl Layouter, + layouter: &mut impl Layouter, ) -> Result<(), Error> { SpreadTableChip::load(config.lookup, layouter) } } -impl Sha256Instructions for Table16Chip { - type State = State; +/// composite of states in table16 +#[allow(clippy::large_enum_variant)] +#[derive(Clone, Debug)] +pub enum Table16State { + /// working state (with spread assignment) for compression rounds + Compress(Box>), + /// the dense state only carry hi-lo 16bit assigned cell used in digest and next block + Dense([RoundWordDense; STATE]), +} + +impl super::Sha256Instructions for Table16Chip { + type State = Table16State; type BlockWord = BlockWord; - fn initialization_vector( - &self, - layouter: &mut impl Layouter, - ) -> Result { - self.config().compression.initialize_with_iv(layouter, IV) + fn initialization_vector(&self, layouter: &mut impl Layouter) -> Result { + >::config(self) + .compression + .initialize_with_iv(layouter, IV) + .map(Box::new) + .map(Table16State::Compress) } fn initialization( &self, - layouter: &mut impl Layouter, + layouter: &mut impl Layouter, init_state: &Self::State, ) -> Result { - self.config() + let dense_state = match init_state.clone() { + Table16State::Compress(s) => { + let (a, b, c, d, e, f, g, h) = s.decompose(); + [ + a.into_dense(), + b.into_dense(), + c.into_dense(), + d, + e.into_dense(), + f.into_dense(), + g.into_dense(), + h, + ] + } + Table16State::Dense(s) => s, + }; + + >::config(self) .compression - .initialize_with_state(layouter, init_state.clone()) + .initialize(layouter, dense_state) + .map(Box::new) + .map(Table16State::Compress) } // Given an initialized state and an input message block, compress the // message block and return the final state. fn compress( &self, - layouter: &mut impl Layouter, + layouter: &mut impl Layouter, initialized_state: &Self::State, input: [Self::BlockWord; super::BLOCK_SIZE], ) -> Result { - let config = self.config(); + let config = >::config(self); let (_, w_halves) = config.message_schedule.process(layouter, input)?; + + let init_working_state = match initialized_state { + Table16State::Compress(s) => s.as_ref().clone(), + _ => panic!("unexpected state type"), + }; + + let final_state = + config + .compression + .compress(layouter, init_working_state.clone(), w_halves)?; + config .compression - .compress(layouter, initialized_state.clone(), w_halves) + .digest(layouter, final_state, init_working_state) + .map(Table16State::Dense) } fn digest( &self, - layouter: &mut impl Layouter, + _layouter: &mut impl Layouter, state: &Self::State, ) -> Result<[Self::BlockWord; super::DIGEST_SIZE], Error> { - // Copy the dense forms of the state variable chunks down to this gate. - // Reconstruct the 32-bit dense words. - self.config().compression.digest(layouter, state.clone()) + let digest_state = match state { + Table16State::Dense(s) => s.clone(), + _ => panic!("unexpected state type"), + }; + + Ok(digest_state.map(|s| s.value()).map(BlockWord)) } } /// Common assignment patterns used by Table16 regions. -trait Table16Assignment { +trait Table16Assignment { /// Assign cells for general spread computation used in sigma, ch, ch_neg, maj gates #[allow(clippy::too_many_arguments)] #[allow(clippy::type_complexity)] fn assign_spread_outputs( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, lookup: &SpreadInputs, a_3: Column, row: usize, @@ -390,8 +467,8 @@ trait Table16Assignment { r_1_odd: Value<[bool; 16]>, ) -> Result< ( - (AssignedBits<16>, AssignedBits<16>), - (AssignedBits<16>, AssignedBits<16>), + (AssignedBits, AssignedBits), + (AssignedBits, AssignedBits), ), Error, > { @@ -432,7 +509,7 @@ trait Table16Assignment { #[allow(clippy::too_many_arguments)] fn assign_sigma_outputs( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, lookup: &SpreadInputs, a_3: Column, row: usize, @@ -440,7 +517,7 @@ trait Table16Assignment { r_0_odd: Value<[bool; 16]>, r_1_even: Value<[bool; 16]>, r_1_odd: Value<[bool; 16]>, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + ) -> Result<(AssignedBits, AssignedBits), 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, )?; @@ -482,7 +559,7 @@ mod tests { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let table16_chip = Table16Chip::construct(config.clone()); + let table16_chip = Table16Chip::construct::(config.clone()); Table16Chip::load(config, &mut layouter)?; // Test vector: "abc" diff --git a/halo2_gadgets/src/sha256/table16/compression.rs b/halo2_gadgets/src/sha256/table16/compression.rs index 62deb42937..1204d2332b 100644 --- a/halo2_gadgets/src/sha256/table16/compression.rs +++ b/halo2_gadgets/src/sha256/table16/compression.rs @@ -1,16 +1,13 @@ use super::{ - super::DIGEST_SIZE, util::{i2lebsp, lebs2ip}, - AssignedBits, BlockWord, SpreadInputs, SpreadVar, Table16Assignment, ROUNDS, STATE, + AssignedBits, Field, SpreadInputs, SpreadVar, Table16Assignment, ROUNDS, STATE, }; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; -use std::convert::TryInto; -use std::ops::Range; +use std::{convert::TryInto, ops::Range}; mod compression_gates; mod compression_util; @@ -72,24 +69,23 @@ pub trait UpperSigmaVar< /// A variable that represents the `[A,B,C,D]` words of the SHA-256 internal state. /// /// The structure of this variable is influenced by the following factors: -/// - In `Σ_0(A)` we need `A` to be split into pieces `(a,b,c,d)` of lengths `(2,11,9,10)` -/// bits respectively (counting from the little end), as well as their spread forms. -/// - `Maj(A,B,C)` requires having the bits of each input in spread form. For `A` we can -/// reuse the pieces from `Σ_0(A)`. Since `B` and `C` are assigned from `A` and `B` -/// respectively in each round, we therefore also have the same pieces in earlier rows. -/// We align the columns to make it efficient to copy-constrain these forms where they -/// are needed. +/// - In `Σ_0(A)` we need `A` to be split into pieces `(a,b,c,d)` of lengths `(2,11,9,10)` bits +/// respectively (counting from the little end), as well as their spread forms. +/// - `Maj(A,B,C)` requires having the bits of each input in spread form. For `A` we can reuse the +/// pieces from `Σ_0(A)`. Since `B` and `C` are assigned from `A` and `B` respectively in each +/// round, we therefore also have the same pieces in earlier rows. We align the columns to make it +/// efficient to copy-constrain these forms where they are needed. #[derive(Clone, Debug)] -pub struct AbcdVar { - a: SpreadVar<2, 4>, - b: SpreadVar<11, 22>, - c_lo: SpreadVar<3, 6>, - c_mid: SpreadVar<3, 6>, - c_hi: SpreadVar<3, 6>, - d: SpreadVar<10, 20>, +pub struct AbcdVar { + a: SpreadVar, + b: SpreadVar, + c_lo: SpreadVar, + c_mid: SpreadVar, + c_hi: SpreadVar, + d: SpreadVar, } -impl AbcdVar { +impl AbcdVar { fn a_range() -> Range { 0..2 } @@ -127,7 +123,7 @@ impl AbcdVar { } } -impl UpperSigmaVar<4, 22, 18, 20> for AbcdVar { +impl UpperSigmaVar<4, 22, 18, 20> for AbcdVar { fn spread_a(&self) -> Value<[bool; 4]> { self.a.spread.value().map(|v| v.0) } @@ -161,24 +157,23 @@ impl UpperSigmaVar<4, 22, 18, 20> for AbcdVar { /// A variable that represents the `[E,F,G,H]` words of the SHA-256 internal state. /// /// The structure of this variable is influenced by the following factors: -/// - In `Σ_1(E)` we need `E` to be split into pieces `(a,b,c,d)` of lengths `(6,5,14,7)` -/// bits respectively (counting from the little end), as well as their spread forms. -/// - `Ch(E,F,G)` requires having the bits of each input in spread form. For `E` we can -/// reuse the pieces from `Σ_1(E)`. Since `F` and `G` are assigned from `E` and `F` -/// respectively in each round, we therefore also have the same pieces in earlier rows. -/// We align the columns to make it efficient to copy-constrain these forms where they -/// are needed. +/// - In `Σ_1(E)` we need `E` to be split into pieces `(a,b,c,d)` of lengths `(6,5,14,7)` bits +/// respectively (counting from the little end), as well as their spread forms. +/// - `Ch(E,F,G)` requires having the bits of each input in spread form. For `E` we can reuse the +/// pieces from `Σ_1(E)`. Since `F` and `G` are assigned from `E` and `F` respectively in each +/// round, we therefore also have the same pieces in earlier rows. We align the columns to make it +/// efficient to copy-constrain these forms where they are needed. #[derive(Clone, Debug)] -pub struct EfghVar { - a_lo: SpreadVar<3, 6>, - a_hi: SpreadVar<3, 6>, - b_lo: SpreadVar<2, 4>, - b_hi: SpreadVar<3, 6>, - c: SpreadVar<14, 28>, - d: SpreadVar<7, 14>, +pub struct EfghVar { + a_lo: SpreadVar, + a_hi: SpreadVar, + b_lo: SpreadVar, + b_hi: SpreadVar, + c: SpreadVar, + d: SpreadVar, } -impl EfghVar { +impl EfghVar { fn a_lo_range() -> Range { 0..3 } @@ -216,7 +211,7 @@ impl EfghVar { } } -impl UpperSigmaVar<12, 10, 28, 14> for EfghVar { +impl UpperSigmaVar<12, 10, 28, 14> for EfghVar { fn spread_a(&self) -> Value<[bool; 12]> { self.a_lo .spread @@ -257,33 +252,37 @@ impl UpperSigmaVar<12, 10, 28, 14> for EfghVar { } #[derive(Clone, Debug)] -pub struct RoundWordDense(AssignedBits<16>, AssignedBits<16>); +pub struct RoundWordDense(AssignedBits, AssignedBits); -impl From<(AssignedBits<16>, AssignedBits<16>)> for RoundWordDense { - fn from(halves: (AssignedBits<16>, AssignedBits<16>)) -> Self { +impl From<(AssignedBits, AssignedBits)> for RoundWordDense { + fn from(halves: (AssignedBits, AssignedBits)) -> Self { Self(halves.0, halves.1) } } -impl RoundWordDense { +impl RoundWordDense { pub fn value(&self) -> Value { self.0 .value_u16() .zip(self.1.value_u16()) .map(|(lo, hi)| lo as u32 + (1 << 16) * hi as u32) } + + pub fn decompose(self) -> (AssignedBits, AssignedBits) { + (self.0, self.1) + } } #[derive(Clone, Debug)] -pub struct RoundWordSpread(AssignedBits<32>, AssignedBits<32>); +pub struct RoundWordSpread(AssignedBits, AssignedBits); -impl From<(AssignedBits<32>, AssignedBits<32>)> for RoundWordSpread { - fn from(halves: (AssignedBits<32>, AssignedBits<32>)) -> Self { +impl From<(AssignedBits, AssignedBits)> for RoundWordSpread { + fn from(halves: (AssignedBits, AssignedBits)) -> Self { Self(halves.0, halves.1) } } -impl RoundWordSpread { +impl RoundWordSpread { pub fn value(&self) -> Value { self.0 .value_u32() @@ -293,17 +292,17 @@ impl RoundWordSpread { } #[derive(Clone, Debug)] -pub struct RoundWordA { - pieces: Option, - dense_halves: RoundWordDense, - spread_halves: Option, +pub struct RoundWordA { + pieces: Option>, + dense_halves: RoundWordDense, + spread_halves: Option>, } -impl RoundWordA { +impl RoundWordA { pub fn new( - pieces: AbcdVar, - dense_halves: RoundWordDense, - spread_halves: RoundWordSpread, + pieces: AbcdVar, + dense_halves: RoundWordDense, + spread_halves: RoundWordSpread, ) -> Self { RoundWordA { pieces: Some(pieces), @@ -312,27 +311,31 @@ impl RoundWordA { } } - pub fn new_dense(dense_halves: RoundWordDense) -> Self { + pub fn new_dense(dense_halves: RoundWordDense) -> Self { RoundWordA { pieces: None, dense_halves, spread_halves: None, } } + + pub fn into_dense(self) -> RoundWordDense { + self.dense_halves + } } #[derive(Clone, Debug)] -pub struct RoundWordE { - pieces: Option, - dense_halves: RoundWordDense, - spread_halves: Option, +pub struct RoundWordE { + pieces: Option>, + dense_halves: RoundWordDense, + spread_halves: Option>, } -impl RoundWordE { +impl RoundWordE { pub fn new( - pieces: EfghVar, - dense_halves: RoundWordDense, - spread_halves: RoundWordSpread, + pieces: EfghVar, + dense_halves: RoundWordDense, + spread_halves: RoundWordSpread, ) -> Self { RoundWordE { pieces: Some(pieces), @@ -341,55 +344,63 @@ impl RoundWordE { } } - pub fn new_dense(dense_halves: RoundWordDense) -> Self { + pub fn new_dense(dense_halves: RoundWordDense) -> Self { RoundWordE { pieces: None, dense_halves, spread_halves: None, } } + + pub fn into_dense(self) -> RoundWordDense { + self.dense_halves + } } #[derive(Clone, Debug)] -pub struct RoundWord { - dense_halves: RoundWordDense, - spread_halves: RoundWordSpread, +pub struct RoundWord { + dense_halves: RoundWordDense, + spread_halves: RoundWordSpread, } -impl RoundWord { - pub fn new(dense_halves: RoundWordDense, spread_halves: RoundWordSpread) -> Self { +impl RoundWord { + pub fn new(dense_halves: RoundWordDense, spread_halves: RoundWordSpread) -> Self { RoundWord { dense_halves, spread_halves, } } + + pub fn into_dense(self) -> RoundWordDense { + self.dense_halves + } } /// The internal state for SHA-256. #[derive(Clone, Debug)] -pub struct State { - a: Option, - b: Option, - c: Option, - d: Option, - e: Option, - f: Option, - g: Option, - h: Option, +pub struct State { + a: Option>, + b: Option>, + c: Option>, + d: Option>, + e: Option>, + f: Option>, + g: Option>, + h: Option>, } -impl State { +impl State { #[allow(clippy::many_single_char_names)] #[allow(clippy::too_many_arguments)] pub fn new( - a: StateWord, - b: StateWord, - c: StateWord, - d: StateWord, - e: StateWord, - f: StateWord, - g: StateWord, - h: StateWord, + a: StateWord, + b: StateWord, + c: StateWord, + d: StateWord, + e: StateWord, + f: StateWord, + g: StateWord, + h: StateWord, ) -> Self { State { a: Some(a), @@ -415,18 +426,57 @@ impl State { h: None, } } + + pub fn decompose( + self, + ) -> ( + RoundWordA, + RoundWord, + RoundWord, + RoundWordDense, + RoundWordE, + RoundWord, + RoundWord, + RoundWordDense, + ) { + compression_util::match_state(self) + } + + #[allow(clippy::many_single_char_names)] + #[allow(clippy::too_many_arguments)] + pub fn composite( + a: RoundWordA, + b: RoundWord, + c: RoundWord, + d: RoundWordDense, + e: RoundWordE, + f: RoundWord, + g: RoundWord, + h: RoundWordDense, + ) -> Self { + Self::new( + StateWord::A(a), + StateWord::B(b), + StateWord::C(c), + StateWord::D(d), + StateWord::E(e), + StateWord::F(f), + StateWord::G(g), + StateWord::H(h), + ) + } } #[derive(Clone, Debug)] -pub enum StateWord { - A(RoundWordA), - B(RoundWord), - C(RoundWord), - D(RoundWordDense), - E(RoundWordE), - F(RoundWord), - G(RoundWord), - H(RoundWordDense), +pub enum StateWord { + A(RoundWordA), + B(RoundWord), + C(RoundWord), + D(RoundWordDense), + E(RoundWordE), + F(RoundWord), + G(RoundWord), + H(RoundWordDense), } #[derive(Clone, Debug)] @@ -453,11 +503,11 @@ pub(super) struct CompressionConfig { s_digest: Selector, } -impl Table16Assignment for CompressionConfig {} +impl Table16Assignment for CompressionConfig {} impl CompressionConfig { - pub(super) fn configure( - meta: &mut ConstraintSystem, + pub(super) fn configure( + meta: &mut ConstraintSystem, lookup: SpreadInputs, message_schedule: Column, extras: [Column; 6], @@ -822,22 +872,25 @@ impl CompressionConfig { // s_digest for final round meta.create_gate("s_digest", |meta| { let s_digest = meta.query_selector(s_digest); - let lo_0 = meta.query_advice(a_3, Rotation::cur()); - let hi_0 = meta.query_advice(a_4, Rotation::cur()); - let word_0 = meta.query_advice(a_5, Rotation::cur()); - let lo_1 = meta.query_advice(a_6, Rotation::cur()); - let hi_1 = meta.query_advice(a_7, Rotation::cur()); - let word_1 = meta.query_advice(a_8, Rotation::cur()); - let lo_2 = meta.query_advice(a_3, Rotation::next()); - let hi_2 = meta.query_advice(a_4, Rotation::next()); - let word_2 = meta.query_advice(a_5, Rotation::next()); - let lo_3 = meta.query_advice(a_6, Rotation::next()); - let hi_3 = meta.query_advice(a_7, Rotation::next()); - let word_3 = meta.query_advice(a_8, Rotation::next()); + let digest_lo = meta.query_advice(a_1, Rotation::cur()); + let digest_hi = meta.query_advice(a_1, Rotation::next()); + let digest_word = meta.query_advice(a_5, Rotation::cur()); + let final_lo = meta.query_advice(a_3, Rotation::cur()); + let final_hi = meta.query_advice(a_3, Rotation::next()); + let initial_lo = meta.query_advice(a_6, Rotation::cur()); + let initial_hi = meta.query_advice(a_6, Rotation::next()); + let digest_carry = meta.query_advice(a_8, Rotation::cur()); CompressionGate::s_digest( - s_digest, lo_0, hi_0, word_0, lo_1, hi_1, word_1, lo_2, hi_2, word_2, lo_3, hi_3, - word_3, + s_digest, + digest_lo, + digest_hi, + digest_word, + final_lo, + final_hi, + initial_lo, + initial_hi, + digest_carry, ) }); @@ -861,11 +914,11 @@ impl CompressionConfig { /// Initialize compression with a constant Initialization Vector of 32-byte words. /// Returns an initialized state. - pub(super) fn initialize_with_iv( + pub(super) fn initialize_with_iv( &self, - layouter: &mut impl Layouter, + layouter: &mut impl Layouter, init_state: [u32; STATE], - ) -> Result { + ) -> Result, Error> { let mut new_state = State::empty_state(); layouter.assign_region( || "initialize_with_iv", @@ -877,18 +930,17 @@ impl CompressionConfig { Ok(new_state) } - /// Initialize compression with some initialized state. This could be a state - /// output from a previous compression round. - pub(super) fn initialize_with_state( + /// Initialize compression with the minimun assignment of state cell. + pub(crate) fn initialize( &self, - layouter: &mut impl Layouter, - init_state: State, - ) -> Result { + layouter: &mut impl Layouter, + init_state_assigned: [RoundWordDense; STATE], + ) -> Result, Error> { let mut new_state = State::empty_state(); layouter.assign_region( || "initialize_with_state", |mut region| { - new_state = self.initialize_state(&mut region, init_state.clone())?; + new_state = self.initialize_state(&mut region, init_state_assigned.clone())?; Ok(()) }, )?; @@ -896,12 +948,12 @@ impl CompressionConfig { } /// Given an initialized state and a message schedule, perform 64 compression rounds. - pub(super) fn compress( + pub(super) fn compress( &self, - layouter: &mut impl Layouter, - initialized_state: State, - w_halves: [(AssignedBits<16>, AssignedBits<16>); ROUNDS], - ) -> Result { + layouter: &mut impl Layouter, + initialized_state: State, + w_halves: [(AssignedBits, AssignedBits); ROUNDS], + ) -> Result, Error> { let mut state = State::empty_state(); layouter.assign_region( || "compress", @@ -917,21 +969,22 @@ impl CompressionConfig { } /// After the final round, convert the state into the final digest. - pub(super) fn digest( + pub(super) fn digest( &self, - layouter: &mut impl Layouter, - state: State, - ) -> Result<[BlockWord; DIGEST_SIZE], Error> { - let mut digest = [BlockWord(Value::known(0)); DIGEST_SIZE]; + layouter: &mut impl Layouter, + last_compress_state: State, + initial_state: State, + ) -> Result<[RoundWordDense; STATE], Error> { layouter.assign_region( || "digest", |mut region| { - digest = self.assign_digest(&mut region, state.clone())?; - - Ok(()) + self.complete_digest( + &mut region, + last_compress_state.clone(), + initial_state.clone(), + ) }, - )?; - Ok(digest) + ) } } @@ -978,15 +1031,17 @@ mod tests { let compression = config.compression.clone(); let initial_state = compression.initialize_with_iv(&mut layouter, IV)?; - let state = config - .compression - .compress(&mut layouter, initial_state, w_halves)?; + let state = + config + .compression + .compress(&mut layouter, initial_state.clone(), w_halves)?; - let digest = config.compression.digest(&mut layouter, state)?; + let digest = config + .compression + .digest(&mut layouter, state, initial_state)?; for (idx, digest_word) in digest.iter().enumerate() { - digest_word.0.assert_if_known(|digest_word| { - (*digest_word as u64 + IV[idx] as u64) as u32 - == super::compression_util::COMPRESSION_OUTPUT[idx] + digest_word.value().assert_if_known(|digest_word| { + *digest_word == super::compression_util::COMPRESSION_OUTPUT[idx] }); } @@ -998,7 +1053,7 @@ mod tests { let prover = match MockProver::::run(17, &circuit, vec![]) { Ok(prover) => prover, - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; assert_eq!(prover.verify(), Ok(())); } diff --git a/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs b/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs index e22a10210c..eccdddfd6f 100644 --- a/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs +++ b/halo2_gadgets/src/sha256/table16/compression/compression_gates.rs @@ -1,4 +1,5 @@ use super::super::{util::*, Gate}; +use crate::utilities::range_check; use halo2_proofs::{ arithmetic::FieldExt, plonk::{Constraint, Constraints, Expression}, @@ -414,30 +415,28 @@ impl CompressionGate { #[allow(clippy::too_many_arguments)] pub fn s_digest( s_digest: Expression, - lo_0: Expression, - hi_0: Expression, - word_0: Expression, - lo_1: Expression, - hi_1: Expression, - word_1: Expression, - lo_2: Expression, - hi_2: Expression, - word_2: Expression, - lo_3: Expression, - hi_3: Expression, - word_3: Expression, + digest_lo: Expression, + digest_hi: Expression, + digest_word: Expression, + final_lo: Expression, + final_hi: Expression, + initial_lo: Expression, + initial_hi: Expression, + digest_carry: Expression, ) -> impl IntoIterator> { - let check_lo_hi = |lo: Expression, hi: Expression, word: Expression| { - lo + hi * F::from(1 << 16) - word - }; + let check_lo_hi = digest_lo.clone() + digest_hi.clone() * F::from(1 << 16) - digest_word; + + let check = + digest_carry.clone() * F::from(1 << 32) + digest_hi * F::from(1 << 16) + digest_lo + - (final_hi + initial_hi) * F::from(1 << 16) + - (final_lo + initial_lo); Constraints::with_selector( s_digest, [ - ("check_lo_hi_0", check_lo_hi(lo_0, hi_0, word_0)), - ("check_lo_hi_1", check_lo_hi(lo_1, hi_1, word_1)), - ("check_lo_hi_2", check_lo_hi(lo_2, hi_2, word_2)), - ("check_lo_hi_3", check_lo_hi(lo_3, hi_3, word_3)), + ("check digest lo_hi", check_lo_hi), + ("digest check", check), + ("check carry bit", range_check(digest_carry, 2)), ], ) } diff --git a/halo2_gadgets/src/sha256/table16/compression/compression_util.rs b/halo2_gadgets/src/sha256/table16/compression/compression_util.rs index 324fe8f695..18666a7b41 100644 --- a/halo2_gadgets/src/sha256/table16/compression/compression_util.rs +++ b/halo2_gadgets/src/sha256/table16/compression/compression_util.rs @@ -1,15 +1,12 @@ +use super::super::{util::*, AssignedBits, SpreadVar, SpreadWord, StateWord, Table16Assignment}; use super::{ - AbcdVar, CompressionConfig, EfghVar, RoundWord, RoundWordA, RoundWordDense, RoundWordE, + AbcdVar, CompressionConfig, EfghVar, Field, RoundWord, RoundWordA, RoundWordDense, RoundWordE, RoundWordSpread, State, UpperSigmaVar, }; -use crate::sha256::table16::{ - util::*, AssignedBits, SpreadVar, SpreadWord, StateWord, Table16Assignment, -}; use halo2_proofs::{ circuit::{Region, Value}, plonk::{Advice, Column, Error}, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; // Test vector 'abc' @@ -111,7 +108,7 @@ pub fn get_round_row(round_idx: RoundIdx) -> usize { RoundIdx::Init => 0, RoundIdx::Main(MainRoundIdx(idx)) => { assert!(idx < 64); - (idx as usize) * SUBREGION_MAIN_WORD + idx * SUBREGION_MAIN_WORD } } } @@ -190,21 +187,17 @@ pub fn get_a_new_row(round_idx: MainRoundIdx) -> usize { get_maj_row(round_idx) } -pub fn get_digest_abcd_row() -> usize { +pub fn get_digest_first_row() -> usize { SUBREGION_MAIN_ROWS } -pub fn get_digest_efgh_row() -> usize { - get_digest_abcd_row() + 2 -} - impl CompressionConfig { - pub(super) fn decompose_abcd( + pub(super) fn decompose_abcd( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, row: usize, val: Value, - ) -> Result { + ) -> Result, Error> { self.s_decompose_abcd.enable(region, row)?; let a_3 = self.extras[0]; @@ -212,7 +205,7 @@ impl CompressionConfig { let a_5 = self.message_schedule; let a_6 = self.extras[2]; - let spread_pieces = val.map(AbcdVar::pieces); + let spread_pieces = val.map(AbcdVar::::pieces); let spread_pieces = spread_pieces.transpose_vec(6); let a = SpreadVar::without_lookup( @@ -270,12 +263,12 @@ impl CompressionConfig { }) } - pub(super) fn decompose_efgh( + pub(super) fn decompose_efgh( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, row: usize, val: Value, - ) -> Result { + ) -> Result, Error> { self.s_decompose_efgh.enable(region, row)?; let a_3 = self.extras[0]; @@ -283,7 +276,7 @@ impl CompressionConfig { let a_5 = self.message_schedule; let a_6 = self.extras[2]; - let spread_pieces = val.map(EfghVar::pieces); + let spread_pieces = val.map(EfghVar::::pieces); let spread_pieces = spread_pieces.transpose_vec(6); let a_lo = SpreadVar::without_lookup( @@ -341,12 +334,12 @@ impl CompressionConfig { }) } - pub(super) fn decompose_a( + pub(super) fn decompose_a( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: RoundIdx, a_val: Value, - ) -> Result { + ) -> Result, Error> { let row = get_decompose_a_row(round_idx); let (dense_halves, spread_halves) = self.assign_word_halves(region, row, a_val)?; @@ -354,12 +347,12 @@ impl CompressionConfig { Ok(RoundWordA::new(a_pieces, dense_halves, spread_halves)) } - pub(super) fn decompose_e( + pub(super) fn decompose_e( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: RoundIdx, e_val: Value, - ) -> Result { + ) -> Result, Error> { let row = get_decompose_e_row(round_idx); let (dense_halves, spread_halves) = self.assign_word_halves(region, row, e_val)?; @@ -367,12 +360,12 @@ impl CompressionConfig { Ok(RoundWordE::new(e_pieces, dense_halves, spread_halves)) } - pub(super) fn assign_upper_sigma_0( + pub(super) fn assign_upper_sigma_0( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - word: AbcdVar, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + word: AbcdVar, + ) -> Result<(AssignedBits, AssignedBits), Error> { // Rename these here for ease of matching the gates to the specification. let a_3 = self.extras[0]; let a_4 = self.extras[1]; @@ -425,12 +418,12 @@ impl CompressionConfig { ) } - pub(super) fn assign_upper_sigma_1( + pub(super) fn assign_upper_sigma_1( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - word: EfghVar, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + word: EfghVar, + ) -> Result<(AssignedBits, AssignedBits), Error> { // Rename these here for ease of matching the gates to the specification. let a_3 = self.extras[0]; let a_4 = self.extras[1]; @@ -484,15 +477,15 @@ impl CompressionConfig { ) } - fn assign_ch_outputs( + fn assign_ch_outputs( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, row: usize, r_0_even: Value<[bool; 16]>, r_0_odd: Value<[bool; 16]>, r_1_even: Value<[bool; 16]>, r_1_odd: Value<[bool; 16]>, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let (_even, odd) = self.assign_spread_outputs( @@ -509,13 +502,13 @@ impl CompressionConfig { Ok(odd) } - pub(super) fn assign_ch( + pub(super) fn assign_ch( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - spread_halves_e: RoundWordSpread, - spread_halves_f: RoundWordSpread, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + spread_halves_e: RoundWordSpread, + spread_halves_f: RoundWordSpread, + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let a_4 = self.extras[1]; @@ -555,13 +548,13 @@ impl CompressionConfig { self.assign_ch_outputs(region, row, p_0_even, p_0_odd, p_1_even, p_1_odd) } - pub(super) fn assign_ch_neg( + pub(super) fn assign_ch_neg( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - spread_halves_e: RoundWordSpread, - spread_halves_g: RoundWordSpread, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + spread_halves_e: RoundWordSpread, + spread_halves_g: RoundWordSpread, + ) -> Result<(AssignedBits, AssignedBits), Error> { let row = get_ch_neg_row(round_idx); self.s_ch_neg.enable(region, row)?; @@ -592,7 +585,7 @@ impl CompressionConfig { .value() .map(|spread_e_lo| negate_spread(spread_e_lo.0)); // Assign spread_neg_e_lo - AssignedBits::<32>::assign_bits( + AssignedBits::::assign_bits( region, || "spread_neg_e_lo", a_3, @@ -606,7 +599,7 @@ impl CompressionConfig { .value() .map(|spread_e_hi| negate_spread(spread_e_hi.0)); // Assign spread_neg_e_hi - AssignedBits::<32>::assign_bits( + AssignedBits::::assign_bits( region, || "spread_neg_e_hi", a_4, @@ -634,15 +627,15 @@ impl CompressionConfig { self.assign_ch_outputs(region, row, p_0_even, p_0_odd, p_1_even, p_1_odd) } - fn assign_maj_outputs( + fn assign_maj_outputs( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, row: usize, r_0_even: Value<[bool; 16]>, r_0_odd: Value<[bool; 16]>, r_1_even: Value<[bool; 16]>, r_1_odd: Value<[bool; 16]>, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let (_even, odd) = self.assign_spread_outputs( region, @@ -658,14 +651,14 @@ impl CompressionConfig { Ok(odd) } - pub(super) fn assign_maj( + pub(super) fn assign_maj( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - spread_halves_a: RoundWordSpread, - spread_halves_b: RoundWordSpread, - spread_halves_c: RoundWordSpread, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + spread_halves_a: RoundWordSpread, + spread_halves_b: RoundWordSpread, + spread_halves_c: RoundWordSpread, + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_4 = self.extras[1]; let a_5 = self.message_schedule; @@ -716,17 +709,17 @@ impl CompressionConfig { // s_h_prime to get H' = H + Ch(E, F, G) + s_upper_sigma_1(E) + K + W #[allow(clippy::too_many_arguments)] - pub(super) fn assign_h_prime( + pub(super) fn assign_h_prime( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - h: RoundWordDense, - ch: (AssignedBits<16>, AssignedBits<16>), - ch_neg: (AssignedBits<16>, AssignedBits<16>), - sigma_1: (AssignedBits<16>, AssignedBits<16>), + h: RoundWordDense, + ch: (AssignedBits, AssignedBits), + ch_neg: (AssignedBits, AssignedBits), + sigma_1: (AssignedBits, AssignedBits), k: u32, - w: &(AssignedBits<16>, AssignedBits<16>), - ) -> Result { + w: &(AssignedBits, AssignedBits), + ) -> Result, Error> { let row = get_h_prime_row(round_idx); self.s_h_prime.enable(region, row)?; @@ -750,8 +743,14 @@ impl CompressionConfig { let k_lo: [bool; 16] = k[..16].try_into().unwrap(); let k_hi: [bool; 16] = k[16..].try_into().unwrap(); { - AssignedBits::<16>::assign_bits(region, || "k_lo", a_6, row - 1, Value::known(k_lo))?; - AssignedBits::<16>::assign_bits(region, || "k_hi", a_6, row, Value::known(k_hi))?; + AssignedBits::::assign_bits( + region, + || "k_lo", + a_6, + row - 1, + Value::known(k_lo), + )?; + AssignedBits::::assign_bits(region, || "k_hi", a_6, row, Value::known(k_hi))?; } // Assign and copy w @@ -783,30 +782,40 @@ impl CompressionConfig { || "h_prime_carry", a_9, row + 1, - || h_prime_carry.map(|value| pallas::Base::from(value as u64)), + || h_prime_carry.map(|value| F::from(value)), )?; let h_prime: Value<[bool; 32]> = h_prime.map(|w| i2lebsp(w.into())); let h_prime_lo: Value<[bool; 16]> = h_prime.map(|w| w[..16].try_into().unwrap()); let h_prime_hi: Value<[bool; 16]> = h_prime.map(|w| w[16..].try_into().unwrap()); - let h_prime_lo = - AssignedBits::<16>::assign_bits(region, || "h_prime_lo", a_7, row + 1, h_prime_lo)?; - let h_prime_hi = - AssignedBits::<16>::assign_bits(region, || "h_prime_hi", a_8, row + 1, h_prime_hi)?; + let h_prime_lo = AssignedBits::::assign_bits( + region, + || "h_prime_lo", + a_7, + row + 1, + h_prime_lo, + )?; + let h_prime_hi = AssignedBits::::assign_bits( + region, + || "h_prime_hi", + a_8, + row + 1, + h_prime_hi, + )?; Ok((h_prime_lo, h_prime_hi).into()) } } // s_e_new to get E_new = H' + D - pub(super) fn assign_e_new( + pub(super) fn assign_e_new( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - d: &RoundWordDense, - h_prime: &RoundWordDense, - ) -> Result { + d: &RoundWordDense, + h_prime: &RoundWordDense, + ) -> Result, Error> { let row = get_e_new_row(round_idx); self.s_e_new.enable(region, row)?; @@ -826,25 +835,20 @@ impl CompressionConfig { ]); 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, - || e_new_carry.map(pallas::Base::from), - )?; + region.assign_advice(|| "e_new_carry", a_9, row + 1, || e_new_carry.map(F::from))?; Ok(e_new_dense) } // s_a_new to get A_new = H' + Maj(A, B, C) + s_upper_sigma_0(A) - pub(super) fn assign_a_new( + pub(super) fn assign_a_new( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - maj: (AssignedBits<16>, AssignedBits<16>), - sigma_0: (AssignedBits<16>, AssignedBits<16>), - h_prime: RoundWordDense, - ) -> Result { + maj: (AssignedBits, AssignedBits), + sigma_0: (AssignedBits, AssignedBits), + h_prime: RoundWordDense, + ) -> Result, Error> { let row = get_a_new_row(round_idx); self.s_a_new.enable(region, row)?; @@ -880,35 +884,30 @@ impl CompressionConfig { ]); 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, - || a_new_carry.map(pallas::Base::from), - )?; + region.assign_advice(|| "a_new_carry", a_9, row, || a_new_carry.map(F::from))?; Ok(a_new_dense) } - pub fn assign_word_halves_dense( + pub fn assign_word_halves_dense( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, lo_row: usize, lo_col: Column, hi_row: usize, hi_col: Column, word: Value, - ) -> Result { + ) -> Result, Error> { let word: Value<[bool; 32]> = word.map(|w| i2lebsp(w.into())); let lo = { let lo: Value<[bool; 16]> = word.map(|w| w[..16].try_into().unwrap()); - AssignedBits::<16>::assign_bits(region, || "lo", lo_col, lo_row, lo)? + AssignedBits::::assign_bits(region, || "lo", lo_col, lo_row, lo)? }; let hi = { let hi: Value<[bool; 16]> = word.map(|w| w[16..].try_into().unwrap()); - AssignedBits::<16>::assign_bits(region, || "hi", hi_col, hi_row, hi)? + AssignedBits::::assign_bits(region, || "hi", hi_col, hi_row, hi)? }; Ok((lo, hi).into()) @@ -916,12 +915,12 @@ impl CompressionConfig { // Assign hi and lo halves for both dense and spread versions of a word #[allow(clippy::type_complexity)] - pub fn assign_word_halves( + pub fn assign_word_halves( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, row: usize, word: Value, - ) -> Result<(RoundWordDense, RoundWordSpread), Error> { + ) -> Result<(RoundWordDense, RoundWordSpread), 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]; @@ -942,17 +941,17 @@ impl CompressionConfig { } #[allow(clippy::many_single_char_names)] -pub fn match_state( - state: State, +pub fn match_state( + state: State, ) -> ( - RoundWordA, - RoundWord, - RoundWord, - RoundWordDense, - RoundWordE, - RoundWord, - RoundWord, - RoundWordDense, + RoundWordA, + RoundWord, + RoundWord, + RoundWordDense, + RoundWordE, + RoundWord, + RoundWord, + RoundWordDense, ) { let a = match state.a { Some(StateWord::A(a)) => a, diff --git a/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs b/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs index aa30f80af7..a22c8cd676 100644 --- a/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs +++ b/halo2_gadgets/src/sha256/table16/compression/subregion_digest.rs @@ -1,102 +1,180 @@ -use super::super::{super::DIGEST_SIZE, BlockWord, RoundWordDense}; -use super::{compression_util::*, CompressionConfig, State}; -use halo2_proofs::{ - circuit::{Region, Value}, - plonk::{Advice, Column, Error}, +use super::super::util::{i2lebsp, sum_with_carry}; +use super::{ + super::{AssignedBits, RoundWordDense, SpreadVar, SpreadWord, STATE}, + compression_util::*, + CompressionConfig, Field, State, }; -use halo2curves::pasta::pallas; +use halo2_proofs::{circuit::Region, plonk::Error}; impl CompressionConfig { + // #[allow(clippy::many_single_char_names)] + // pub fn assign_digest( + // &self, + // region: &mut Region<'_, F>, + // state: State, + // ) -> Result<[BlockWord; DIGEST_SIZE], Error> { + // let a_3 = self.extras[0]; + // let a_4 = self.extras[1]; + // let a_5 = self.message_schedule; + // let a_6 = self.extras[2]; + // let a_7 = self.extras[3]; + // let a_8 = self.extras[4]; + + // let (a, b, c, d, e, f, g, h) = match_state(state); + + // let abcd_row = 0; + // self.s_digest.enable(region, abcd_row)?; + // let efgh_row = abcd_row + 2; + // self.s_digest.enable(region, efgh_row)?; + + // // Assign digest for A, B, C, D + // a.dense_halves + // .0 + // .copy_advice(|| "a_lo", region, a_3, abcd_row)?; + // a.dense_halves + // .1 + // .copy_advice(|| "a_hi", region, a_4, abcd_row)?; + // let a = a.dense_halves.value(); + // region.assign_advice(|| "a", a_5, abcd_row, || a.map(|a| F::from(a as u64)))?; + + // 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)?; + + // // Assign digest for E, F, G, H + // e.dense_halves + // .0 + // .copy_advice(|| "e_lo", region, a_3, efgh_row)?; + // e.dense_halves + // .1 + // .copy_advice(|| "e_hi", region, a_4, efgh_row)?; + // let e = e.dense_halves.value(); + // region.assign_advice(|| "e", a_5, efgh_row, || e.map(|e| F::from(e as u64)))?; + + // 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)?; + + // Ok([ + // BlockWord(a), + // BlockWord(b), + // BlockWord(c), + // BlockWord(d), + // BlockWord(e), + // BlockWord(f), + // BlockWord(g), + // BlockWord(h), + // ]) + // } + + // fn assign_digest_word( + // &self, + // region: &mut Region<'_, F>, + // row: usize, + // lo_col: Column, + // hi_col: Column, + // word_col: Column, + // dense_halves: RoundWordDense, + // ) -> Result, Error> { + // dense_halves.0.copy_advice(|| "lo", region, lo_col, row)?; + // dense_halves.1.copy_advice(|| "hi", region, hi_col, row)?; + + // let val = dense_halves.value(); + // region.assign_advice( + // || "word", + // word_col, + // row, + // || val.map(|val| F::from(val as u64)), + // )?; + + // Ok(val) + // } + #[allow(clippy::many_single_char_names)] - pub fn assign_digest( + pub fn complete_digest( &self, - region: &mut Region<'_, pallas::Base>, - state: State, - ) -> Result<[BlockWord; DIGEST_SIZE], Error> { + region: &mut Region<'_, F>, + last_compress_state: State, + initial_state: State, + ) -> Result<[RoundWordDense; STATE], Error> { let a_3 = self.extras[0]; - let a_4 = self.extras[1]; let a_5 = self.message_schedule; let a_6 = self.extras[2]; - let a_7 = self.extras[3]; let a_8 = self.extras[4]; - let (a, b, c, d, e, f, g, h) = match_state(state); - - let abcd_row = 0; - self.s_digest.enable(region, abcd_row)?; - let efgh_row = abcd_row + 2; - self.s_digest.enable(region, efgh_row)?; - - // Assign digest for A, B, C, D - a.dense_halves - .0 - .copy_advice(|| "a_lo", region, a_3, abcd_row)?; - a.dense_halves - .1 - .copy_advice(|| "a_hi", region, a_4, abcd_row)?; - let a = a.dense_halves.value(); - region.assign_advice( - || "a", - a_5, - abcd_row, - || a.map(|a| pallas::Base::from(a as u64)), - )?; - - 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)?; - - // Assign digest for E, F, G, H - e.dense_halves - .0 - .copy_advice(|| "e_lo", region, a_3, efgh_row)?; - e.dense_halves - .1 - .copy_advice(|| "e_hi", region, a_4, efgh_row)?; - let e = e.dense_halves.value(); - region.assign_advice( - || "e", - a_5, - efgh_row, - || e.map(|e| pallas::Base::from(e as u64)), - )?; - - 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)?; - - Ok([ - BlockWord(a), - BlockWord(b), - BlockWord(c), - BlockWord(d), - BlockWord(e), - BlockWord(f), - BlockWord(g), - BlockWord(h), + let (a, b, c, d, e, f, g, h) = match_state(last_compress_state); + let (a_i, b_i, c_i, d_i, e_i, f_i, g_i, h_i) = match_state(initial_state); + + let mut digest_dense = Vec::new(); + for (i, (final_dense, init_dense)) in [ + a.dense_halves, + b.dense_halves, + c.dense_halves, + d, + e.dense_halves, + f.dense_halves, + g.dense_halves, + h, + ] + .into_iter() + .zip([ + a_i.dense_halves, + b_i.dense_halves, + c_i.dense_halves, + d_i, + e_i.dense_halves, + f_i.dense_halves, + g_i.dense_halves, + h_i, ]) - } + .enumerate() + { + let row = i * 2; + self.s_digest.enable(region, row)?; + let (final_lo, final_hi) = final_dense.decompose(); + let (init_lo, init_hi) = init_dense.decompose(); - fn assign_digest_word( - &self, - region: &mut Region<'_, pallas::Base>, - row: usize, - lo_col: Column, - hi_col: Column, - word_col: Column, - dense_halves: RoundWordDense, - ) -> Result, Error> { - dense_halves.0.copy_advice(|| "lo", region, lo_col, row)?; - dense_halves.1.copy_advice(|| "hi", region, hi_col, row)?; - - let val = dense_halves.value(); - region.assign_advice( - || "word", - word_col, - row, - || val.map(|val| pallas::Base::from(val as u64)), - )?; - - Ok(val) + let (digest, carry) = sum_with_carry(vec![ + (final_lo.value_u16(), final_hi.value_u16()), + (init_lo.value_u16(), init_hi.value_u16()), + ]); + + region.assign_advice(|| "digest carry", a_8, row, || carry.map(F::from))?; + region.assign_advice( + || "digest word", + a_5, + row, + || digest.map(|v| F::from(v as u64)), + )?; + + final_lo.copy_advice(|| "final lo", region, a_3, row)?; + final_hi.copy_advice(|| "final hi", region, a_3, row + 1)?; + init_lo.copy_advice(|| "init lo", region, a_6, row)?; + init_hi.copy_advice(|| "init hi", region, a_6, row + 1)?; + + let word = digest.map(|w| i2lebsp(w.into())); + let digest_lo = word.map(|w: [bool; 32]| w[..16].try_into().unwrap()); + let digest_hi = word.map(|w| w[16..].try_into().unwrap()); + + let digest_lo = SpreadVar::with_lookup( + region, + &self.lookup, + row, + digest_lo.map(SpreadWord::<16, 32>::new), + )? + .dense; + let digest_hi = SpreadVar::with_lookup( + region, + &self.lookup, + row + 1, + digest_hi.map(SpreadWord::<16, 32>::new), + )? + .dense; + digest_dense.push((digest_lo, digest_hi)) + } + + let ret: [(AssignedBits, AssignedBits); STATE] = + digest_dense.try_into().unwrap(); + Ok(ret.map(RoundWordDense::from)) } } diff --git a/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs b/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs index a487dc0c87..9b0c4341bd 100644 --- a/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs +++ b/halo2_gadgets/src/sha256/table16/compression/subregion_initial.rs @@ -1,19 +1,21 @@ -use super::super::{RoundWord, StateWord, STATE}; -use super::{compression_util::*, CompressionConfig, State}; +use super::{ + super::{RoundWord, StateWord, STATE}, + compression_util::*, + CompressionConfig, Field, RoundWordDense, State, +}; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; impl CompressionConfig { #[allow(clippy::many_single_char_names)] - pub fn initialize_iv( + pub fn initialize_iv( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, iv: [u32; STATE], - ) -> Result { + ) -> Result, Error> { let a_7 = self.extras[3]; // Decompose E into (6, 5, 14, 7)-bit chunks @@ -53,43 +55,37 @@ impl CompressionConfig { } #[allow(clippy::many_single_char_names)] - pub fn initialize_state( + pub fn initialize_state( &self, - region: &mut Region<'_, pallas::Base>, - state: State, - ) -> Result { + region: &mut Region<'_, F>, + state_dense: [RoundWordDense; STATE], + ) -> Result, Error> { + // TODO: there is no constraint on the input state and the output decomposed state + let a_7 = self.extras[3]; - let (a, b, c, d, e, f, g, h) = match_state(state); + let [a, b, c, d, e, f, g, h] = state_dense; // Decompose E into (6, 5, 14, 7)-bit chunks - let e = e.dense_halves.value(); - let e = self.decompose_e(region, RoundIdx::Init, e)?; + let e = self.decompose_e(region, RoundIdx::Init, e.value())?; // Decompose F, G - let f = f.dense_halves.value(); - let f = self.decompose_f(region, InitialRound, f)?; - let g = g.dense_halves.value(); - let g = self.decompose_g(region, InitialRound, g)?; + let f = self.decompose_f(region, InitialRound, f.value())?; + let g = self.decompose_g(region, InitialRound, g.value())?; // Assign H - let h = h.value(); let h_row = get_h_row(RoundIdx::Init); - let h = self.assign_word_halves_dense(region, h_row, a_7, h_row + 1, a_7, h)?; + let h = self.assign_word_halves_dense(region, h_row, a_7, h_row + 1, a_7, h.value())?; // Decompose A into (2, 11, 9, 10)-bit chunks - let a = a.dense_halves.value(); - let a = self.decompose_a(region, RoundIdx::Init, a)?; + let a = self.decompose_a(region, RoundIdx::Init, a.value())?; // Decompose B, C - let b = b.dense_halves.value(); - let b = self.decompose_b(region, InitialRound, b)?; - let c = c.dense_halves.value(); - let c = self.decompose_c(region, InitialRound, c)?; + let b = self.decompose_b(region, InitialRound, b.value())?; + let c = self.decompose_c(region, InitialRound, c.value())?; // Assign D - let d = d.value(); let d_row = get_d_row(RoundIdx::Init); - let d = self.assign_word_halves_dense(region, d_row, a_7, d_row + 1, a_7, d)?; + let d = self.assign_word_halves_dense(region, d_row, a_7, d_row + 1, a_7, d.value())?; Ok(State::new( StateWord::A(a), @@ -103,12 +99,12 @@ impl CompressionConfig { )) } - fn decompose_b( + fn decompose_b( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: InitialRound, b_val: Value, - ) -> Result { + ) -> Result, Error> { let row = get_decompose_b_row(round_idx); let (dense_halves, spread_halves) = self.assign_word_halves(region, row, b_val)?; @@ -116,12 +112,12 @@ impl CompressionConfig { Ok(RoundWord::new(dense_halves, spread_halves)) } - fn decompose_c( + fn decompose_c( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: InitialRound, c_val: Value, - ) -> Result { + ) -> Result, Error> { let row = get_decompose_c_row(round_idx); let (dense_halves, spread_halves) = self.assign_word_halves(region, row, c_val)?; @@ -129,12 +125,12 @@ impl CompressionConfig { Ok(RoundWord::new(dense_halves, spread_halves)) } - fn decompose_f( + fn decompose_f( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: InitialRound, f_val: Value, - ) -> Result { + ) -> Result, Error> { let row = get_decompose_f_row(round_idx); let (dense_halves, spread_halves) = self.assign_word_halves(region, row, f_val)?; @@ -142,12 +138,12 @@ impl CompressionConfig { Ok(RoundWord::new(dense_halves, spread_halves)) } - fn decompose_g( + fn decompose_g( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: InitialRound, g_val: Value, - ) -> Result { + ) -> Result, Error> { let row = get_decompose_g_row(round_idx); let (dense_halves, spread_halves) = self.assign_word_halves(region, row, g_val)?; diff --git a/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs b/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs index bda188a866..ab79849790 100644 --- a/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs +++ b/halo2_gadgets/src/sha256/table16/compression/subregion_main.rs @@ -1,19 +1,19 @@ -use super::super::{AssignedBits, RoundWord, RoundWordA, RoundWordE, StateWord, ROUND_CONSTANTS}; -use super::{compression_util::*, CompressionConfig, State}; +use super::{ + super::{AssignedBits, RoundWord, RoundWordA, RoundWordE, StateWord, ROUND_CONSTANTS}, + compression_util::*, + CompressionConfig, Field, State, +}; use halo2_proofs::{circuit::Region, plonk::Error}; -use halo2curves::pasta::pallas; impl CompressionConfig { #[allow(clippy::many_single_char_names)] - pub fn assign_round( + pub fn assign_round( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, round_idx: MainRoundIdx, - state: State, - schedule_word: &(AssignedBits<16>, AssignedBits<16>), - ) -> Result { - let a_3 = self.extras[0]; - let a_4 = self.extras[1]; + state: State, + schedule_word: &(AssignedBits, AssignedBits), + ) -> Result, Error> { let a_7 = self.extras[3]; let (a, b, c, d, e, f, g, h) = match_state(state); @@ -103,21 +103,12 @@ impl CompressionConfig { StateWord::H(g.dense_halves), )) } 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::A(RoundWordA::new_dense(a_new_dense)), StateWord::B(RoundWord::new(a.dense_halves, a.spread_halves.unwrap())), StateWord::C(b), StateWord::D(c.dense_halves), - StateWord::E(RoundWordE::new_dense(e_final)), + StateWord::E(RoundWordE::new_dense(e_new_dense)), StateWord::F(RoundWord::new(e.dense_halves, e.spread_halves.unwrap())), StateWord::G(f), StateWord::H(g.dense_halves), diff --git a/halo2_gadgets/src/sha256/table16/message_schedule.rs b/halo2_gadgets/src/sha256/table16/message_schedule.rs index 690e086c49..792e980ff8 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule.rs @@ -1,12 +1,13 @@ use std::convert::TryInto; -use super::{super::BLOCK_SIZE, AssignedBits, BlockWord, SpreadInputs, Table16Assignment, ROUNDS}; +use super::{ + super::BLOCK_SIZE, AssignedBits, BlockWord, Field, SpreadInputs, Table16Assignment, ROUNDS, +}; use halo2_proofs::{ circuit::Layouter, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; -use halo2curves::pasta::pallas; mod schedule_gates; mod schedule_util; @@ -21,10 +22,10 @@ use schedule_util::*; pub use schedule_util::msg_schedule_test_input; #[derive(Clone, Debug)] -pub(super) struct MessageWord(AssignedBits<32>); +pub(super) struct MessageWord(AssignedBits); -impl std::ops::Deref for MessageWord { - type Target = AssignedBits<32>; +impl std::ops::Deref for MessageWord { + type Target = AssignedBits; fn deref(&self) -> &Self::Target { &self.0 @@ -57,7 +58,7 @@ pub(super) struct MessageScheduleConfig { s_lower_sigma_1_v2: Selector, } -impl Table16Assignment for MessageScheduleConfig {} +impl Table16Assignment for MessageScheduleConfig {} impl MessageScheduleConfig { /// Configures the message schedule. @@ -70,8 +71,8 @@ impl MessageScheduleConfig { /// gates, and will not place any constraints on (such as lookup constraints) outside /// itself. #[allow(clippy::many_single_char_names)] - pub(super) fn configure( - meta: &mut ConstraintSystem, + pub(super) fn configure( + meta: &mut ConstraintSystem, lookup: SpreadInputs, message_schedule: Column, extras: [Column; 6], @@ -302,25 +303,25 @@ impl MessageScheduleConfig { } #[allow(clippy::type_complexity)] - pub(super) fn process( + pub(super) fn process( &self, - layouter: &mut impl Layouter, + layouter: &mut impl Layouter, input: [BlockWord; BLOCK_SIZE], ) -> Result< ( - [MessageWord; ROUNDS], - [(AssignedBits<16>, AssignedBits<16>); ROUNDS], + [MessageWord; ROUNDS], + [(AssignedBits, AssignedBits); ROUNDS], ), Error, > { - let mut w = Vec::::with_capacity(ROUNDS); - let mut w_halves = Vec::<(AssignedBits<16>, AssignedBits<16>)>::with_capacity(ROUNDS); + let mut w = Vec::>::with_capacity(ROUNDS); + let mut w_halves = Vec::<(AssignedBits<_, 16>, AssignedBits<_, 16>)>::with_capacity(ROUNDS); layouter.assign_region( || "process message block", |mut region| { - w = Vec::::with_capacity(ROUNDS); - w_halves = Vec::<(AssignedBits<16>, AssignedBits<16>)>::with_capacity(ROUNDS); + w = Vec::>::with_capacity(ROUNDS); + w_halves = Vec::<(AssignedBits<_, 16>, AssignedBits<_, 16>)>::with_capacity(ROUNDS); // Assign all fixed columns for index in 1..14 { @@ -393,10 +394,13 @@ impl MessageScheduleConfig { #[cfg(test)] mod tests { - use super::super::{ - super::BLOCK_SIZE, util::lebs2ip, BlockWord, SpreadTableChip, Table16Chip, Table16Config, + use super::{ + super::{ + super::BLOCK_SIZE, util::lebs2ip, BlockWord, SpreadTableChip, Table16Chip, + Table16Config, + }, + schedule_util::*, }; - use super::schedule_util::*; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::MockProver, @@ -448,7 +452,7 @@ mod tests { let prover = match MockProver::::run(17, &circuit, vec![]) { Ok(prover) => prover, - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; assert_eq!(prover.verify(), Ok(())); } diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs index 79a9fa2621..6c092dc361 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs @@ -1,10 +1,9 @@ -use super::super::AssignedBits; -use super::MessageScheduleConfig; +use super::super::Field; +use super::{super::AssignedBits, MessageScheduleConfig}; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; #[cfg(test)] use super::super::{super::BLOCK_SIZE, BlockWord, ROUNDS}; @@ -40,20 +39,17 @@ pub fn get_word_row(word_idx: usize) -> usize { if word_idx == 0 { 0 } else if (1..=13).contains(&word_idx) { - SUBREGION_0_ROWS + SUBREGION_1_WORD * (word_idx - 1) as usize + SUBREGION_0_ROWS + SUBREGION_1_WORD * (word_idx - 1) } else if (14..=48).contains(&word_idx) { SUBREGION_0_ROWS + SUBREGION_1_ROWS + SUBREGION_2_WORD * (word_idx - 14) + 1 } else if (49..=61).contains(&word_idx) { - SUBREGION_0_ROWS - + SUBREGION_1_ROWS - + SUBREGION_2_ROWS - + SUBREGION_3_WORD * (word_idx - 49) as usize + SUBREGION_0_ROWS + SUBREGION_1_ROWS + SUBREGION_2_ROWS + SUBREGION_3_WORD * (word_idx - 49) } else { SUBREGION_0_ROWS + SUBREGION_1_ROWS + SUBREGION_2_ROWS + SUBREGION_3_ROWS - + DECOMPOSE_0_ROWS * (word_idx - 62) as usize + + DECOMPOSE_0_ROWS * (word_idx - 62) } } @@ -150,12 +146,18 @@ pub const MSG_SCHEDULE_TEST_OUTPUT: [u32; ROUNDS] = [ impl MessageScheduleConfig { // Assign a word and its hi and lo halves - pub fn assign_word_and_halves( + pub fn assign_word_and_halves( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, word: Value, word_idx: usize, - ) -> Result<(AssignedBits<32>, (AssignedBits<16>, AssignedBits<16>)), Error> { + ) -> Result< + ( + AssignedBits, + (AssignedBits, AssignedBits), + ), + Error, + > { // Rename these here for ease of matching the gates to the specification. let a_3 = self.extras[0]; let a_4 = self.extras[1]; @@ -164,16 +166,28 @@ impl MessageScheduleConfig { let w_lo = { let w_lo_val = word.map(|word| word as u16); - AssignedBits::<16>::assign(region, || format!("W_{}_lo", word_idx), a_3, row, w_lo_val)? + AssignedBits::<_, 16>::assign( + region, + || format!("W_{word_idx}_lo"), + a_3, + row, + w_lo_val, + )? }; let w_hi = { let w_hi_val = word.map(|word| (word >> 16) as u16); - AssignedBits::<16>::assign(region, || format!("W_{}_hi", word_idx), a_4, row, w_hi_val)? + AssignedBits::<_, 16>::assign( + region, + || format!("W_{word_idx}_hi"), + a_4, + row, + w_hi_val, + )? }; - let word = AssignedBits::<32>::assign( + let word = AssignedBits::<_, 32>::assign( region, - || format!("W_{}", word_idx), + || format!("W_{word_idx}"), self.message_schedule, row, word, diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs index 947c9dda2a..2fa0474881 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs @@ -1,26 +1,29 @@ -use super::super::{util::*, AssignedBits, BlockWord, SpreadVar, SpreadWord, Table16Assignment}; -use super::{schedule_util::*, MessageScheduleConfig}; +use super::super::Field; +use super::{ + super::{util::*, AssignedBits, BlockWord, SpreadVar, SpreadWord, Table16Assignment}, + schedule_util::*, + MessageScheduleConfig, +}; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; // A word in subregion 1 // (3, 4, 11, 14)-bit chunks #[derive(Debug)] -pub struct Subregion1Word { +pub struct Subregion1Word { index: usize, - a: AssignedBits<3>, - b: AssignedBits<4>, - c: AssignedBits<11>, - d: AssignedBits<14>, - spread_c: AssignedBits<22>, - spread_d: AssignedBits<28>, + a: AssignedBits, + b: AssignedBits, + c: AssignedBits, + d: AssignedBits, + spread_c: AssignedBits, + spread_d: AssignedBits, } -impl Subregion1Word { +impl Subregion1Word { fn spread_a(&self) -> Value<[bool; 6]> { self.a.value().map(|v| v.spread()) } @@ -75,11 +78,11 @@ impl Subregion1Word { } impl MessageScheduleConfig { - pub fn assign_subregion1( + pub fn assign_subregion1( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, input: &[BlockWord], - ) -> Result, AssignedBits<16>)>, Error> { + ) -> Result, AssignedBits)>, Error> { assert_eq!(input.len(), SUBREGION_1_LEN); Ok(input .iter() @@ -101,12 +104,12 @@ impl MessageScheduleConfig { } /// Pieces of length [3, 4, 11, 14] - fn decompose_subregion1_word( + fn decompose_subregion1_word( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, word: Value<[bool; 32]>, index: usize, - ) -> Result { + ) -> Result, Error> { let row = get_word_row(index); // Rename these here for ease of matching the gates to the specification. @@ -124,11 +127,21 @@ impl MessageScheduleConfig { let pieces = pieces.transpose_vec(4); // Assign `a` (3-bit piece) - let a = - AssignedBits::<3>::assign_bits(region, || "word_a", a_3, row + 1, pieces[0].clone())?; + let a = AssignedBits::<_, 3>::assign_bits( + region, + || "word_a", + a_3, + row + 1, + pieces[0].clone(), + )?; // Assign `b` (4-bit piece) - let b = - AssignedBits::<4>::assign_bits(region, || "word_b", a_4, row + 1, pieces[1].clone())?; + let b = AssignedBits::<_, 4>::assign_bits( + region, + || "word_b", + a_4, + row + 1, + pieces[1].clone(), + )?; // Assign `c` (11-bit piece) lookup let spread_c = pieces[2].clone().map(SpreadWord::try_new); @@ -151,11 +164,11 @@ impl MessageScheduleConfig { // sigma_0 v1 on a word in W_1 to W_13 // (3, 4, 11, 14)-bit chunks - fn lower_sigma_0( + fn lower_sigma_0( &self, - region: &mut Region<'_, pallas::Base>, - word: Subregion1Word, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + region: &mut Region<'_, F>, + word: Subregion1Word, + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let a_4 = self.extras[1]; let a_5 = self.message_schedule; @@ -168,16 +181,16 @@ impl MessageScheduleConfig { // Witness `spread_a` let spread_a = word.a.value().map(|bits| spread_bits(bits.0)); - AssignedBits::<6>::assign_bits(region, || "spread_a", a_6, row + 1, spread_a)?; + AssignedBits::<_, 6>::assign_bits(region, || "spread_a", a_6, row + 1, spread_a)?; // Split `b` (4-bit chunk) into `b_hi` and `b_lo` // Assign `b_lo`, `spread_b_lo` let b_lo: Value<[bool; 2]> = word.b.value().map(|b| b.0[..2].try_into().unwrap()); let spread_b_lo = b_lo.map(spread_bits); { - AssignedBits::<2>::assign_bits(region, || "b_lo", a_3, row - 1, b_lo)?; + AssignedBits::<_, 2>::assign_bits(region, || "b_lo", a_3, row - 1, b_lo)?; - AssignedBits::<4>::assign_bits(region, || "spread_b_lo", a_4, row - 1, spread_b_lo)?; + AssignedBits::<_, 4>::assign_bits(region, || "spread_b_lo", a_4, row - 1, spread_b_lo)?; }; // Split `b` (2-bit chunk) into `b_hi` and `b_lo` @@ -185,9 +198,9 @@ impl MessageScheduleConfig { let b_hi: Value<[bool; 2]> = word.b.value().map(|b| b.0[2..].try_into().unwrap()); let spread_b_hi = b_hi.map(spread_bits); { - AssignedBits::<2>::assign_bits(region, || "b_hi", a_5, row - 1, b_hi)?; + AssignedBits::<_, 2>::assign_bits(region, || "b_hi", a_5, row - 1, b_hi)?; - AssignedBits::<4>::assign_bits(region, || "spread_b_hi", a_6, row - 1, spread_b_hi)?; + AssignedBits::<_, 4>::assign_bits(region, || "spread_b_hi", a_6, row - 1, spread_b_hi)?; }; // Assign `b` and copy constraint diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs index 43e96c934f..18386995c5 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs @@ -1,29 +1,32 @@ -use super::super::{util::*, AssignedBits, Bits, SpreadVar, SpreadWord, Table16Assignment}; -use super::{schedule_util::*, MessageScheduleConfig, MessageWord}; +use super::super::Field; +use super::{ + super::{util::*, AssignedBits, Bits, SpreadVar, SpreadWord, Table16Assignment}, + schedule_util::*, + MessageScheduleConfig, MessageWord, +}; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; /// A word in subregion 2 /// (3, 4, 3, 7, 1, 1, 13)-bit chunks #[derive(Clone, Debug)] -pub struct Subregion2Word { +pub struct Subregion2Word { index: usize, - a: AssignedBits<3>, - b: AssignedBits<4>, - c: AssignedBits<3>, - d: AssignedBits<7>, - e: AssignedBits<1>, - f: AssignedBits<1>, - g: AssignedBits<13>, - spread_d: AssignedBits<14>, - spread_g: AssignedBits<26>, + a: AssignedBits, + b: AssignedBits, + c: AssignedBits, + d: AssignedBits, + e: AssignedBits, + f: AssignedBits, + g: AssignedBits, + spread_d: AssignedBits, + spread_g: AssignedBits, } -impl Subregion2Word { +impl Subregion2Word { fn spread_a(&self) -> Value<[bool; 6]> { self.a.value().map(|v| v.spread()) } @@ -153,13 +156,13 @@ impl Subregion2Word { impl MessageScheduleConfig { // W_[14..49] - pub fn assign_subregion2( + pub fn assign_subregion2( &self, - region: &mut Region<'_, pallas::Base>, - lower_sigma_0_output: Vec<(AssignedBits<16>, AssignedBits<16>)>, - w: &mut Vec, - w_halves: &mut Vec<(AssignedBits<16>, AssignedBits<16>)>, - ) -> Result, AssignedBits<16>)>, Error> { + region: &mut Region<'_, F>, + lower_sigma_0_output: Vec<(AssignedBits, AssignedBits)>, + w: &mut Vec>, + w_halves: &mut Vec<(AssignedBits, AssignedBits)>, + ) -> Result, AssignedBits)>, Error> { let a_5 = self.message_schedule; let a_6 = self.extras[2]; let a_7 = self.extras[3]; @@ -167,9 +170,9 @@ impl MessageScheduleConfig { let a_9 = self.extras[5]; let mut lower_sigma_0_v2_results = - Vec::<(AssignedBits<16>, AssignedBits<16>)>::with_capacity(SUBREGION_2_LEN); + Vec::<(AssignedBits<_, 16>, AssignedBits<_, 16>)>::with_capacity(SUBREGION_2_LEN); let mut lower_sigma_1_v2_results = - Vec::<(AssignedBits<16>, AssignedBits<16>)>::with_capacity(SUBREGION_2_LEN); + Vec::<(AssignedBits<_, 16>, AssignedBits<_, 16>)>::with_capacity(SUBREGION_2_LEN); // Closure to compose new word // W_i = sigma_1(W_{i - 2}) + W_{i - 7} + sigma_0(W_{i - 15}) + W_{i - 16} @@ -179,98 +182,99 @@ impl MessageScheduleConfig { // sigma_0_v2(W_[14..36]) will be used to get the new W_[29..51] // sigma_1_v2(W_[14..49]) will be used to get the W_[16..51] // The lowest-index words involved will be W_[0..13] - let mut new_word = |idx: usize, - sigma_0_output: &(AssignedBits<16>, AssignedBits<16>)| - -> Result, AssignedBits<16>)>, Error> { - // Decompose word into (3, 4, 3, 7, 1, 1, 13)-bit chunks - let word = self.decompose_word(region, w[idx].value(), idx)?; - - // sigma_0 v2 and sigma_1 v2 on word - lower_sigma_0_v2_results.push(self.lower_sigma_0_v2(region, word.clone())?); - lower_sigma_1_v2_results.push(self.lower_sigma_1_v2(region, word)?); - - let new_word_idx = idx + 2; - - // Copy sigma_0(W_{i - 15}) output from Subregion 1 - sigma_0_output.0.copy_advice( - || format!("sigma_0(W_{})_lo", new_word_idx - 15), - region, - a_6, - get_word_row(new_word_idx - 16), - )?; - sigma_0_output.1.copy_advice( - || format!("sigma_0(W_{})_hi", new_word_idx - 15), - region, - a_6, - get_word_row(new_word_idx - 16) + 1, - )?; - - // Copy sigma_1(W_{i - 2}) - lower_sigma_1_v2_results[new_word_idx - 16].0.copy_advice( - || format!("sigma_1(W_{})_lo", new_word_idx - 2), - region, - a_7, - get_word_row(new_word_idx - 16), - )?; - lower_sigma_1_v2_results[new_word_idx - 16].1.copy_advice( - || format!("sigma_1(W_{})_hi", new_word_idx - 2), - region, - a_7, - get_word_row(new_word_idx - 16) + 1, - )?; - - // Copy W_{i - 7} - w_halves[new_word_idx - 7].0.copy_advice( - || format!("W_{}_lo", new_word_idx - 7), - region, - a_8, - get_word_row(new_word_idx - 16), - )?; - w_halves[new_word_idx - 7].1.copy_advice( - || format!("W_{}_hi", new_word_idx - 7), - region, - a_8, - get_word_row(new_word_idx - 16) + 1, - )?; - - // Calculate W_i, carry_i - let (word, carry) = sum_with_carry(vec![ - ( - lower_sigma_1_v2_results[new_word_idx - 16].0.value_u16(), - lower_sigma_1_v2_results[new_word_idx - 16].1.value_u16(), - ), - ( - w_halves[new_word_idx - 7].0.value_u16(), - w_halves[new_word_idx - 7].1.value_u16(), - ), - (sigma_0_output.0.value_u16(), sigma_0_output.1.value_u16()), - ( - w_halves[new_word_idx - 16].0.value_u16(), - w_halves[new_word_idx - 16].1.value_u16(), - ), - ]); - - // Assign W_i, carry_i - region.assign_advice( - || format!("W_{}", new_word_idx), - a_5, - get_word_row(new_word_idx - 16) + 1, - || word.map(|word| pallas::Base::from(word as u64)), - )?; - region.assign_advice( - || format!("carry_{}", new_word_idx), - a_9, - get_word_row(new_word_idx - 16) + 1, - || carry.map(|carry| pallas::Base::from(carry as u64)), - )?; - let (word, halves) = self.assign_word_and_halves(region, word, new_word_idx)?; - w.push(MessageWord(word)); - w_halves.push(halves); - - Ok(lower_sigma_0_v2_results.clone()) - }; - - let mut tmp_lower_sigma_0_v2_results: Vec<(AssignedBits<16>, AssignedBits<16>)> = + let mut new_word = + |idx: usize, + sigma_0_output: &(AssignedBits<_, 16>, AssignedBits<_, 16>)| + -> Result, AssignedBits<_, 16>)>, Error> { + // Decompose word into (3, 4, 3, 7, 1, 1, 13)-bit chunks + let word = self.decompose_word(region, w[idx].value(), idx)?; + + // sigma_0 v2 and sigma_1 v2 on word + lower_sigma_0_v2_results.push(self.lower_sigma_0_v2(region, word.clone())?); + lower_sigma_1_v2_results.push(self.lower_sigma_1_v2(region, word)?); + + let new_word_idx = idx + 2; + + // Copy sigma_0(W_{i - 15}) output from Subregion 1 + sigma_0_output.0.copy_advice( + || format!("sigma_0(W_{})_lo", new_word_idx - 15), + region, + a_6, + get_word_row(new_word_idx - 16), + )?; + sigma_0_output.1.copy_advice( + || format!("sigma_0(W_{})_hi", new_word_idx - 15), + region, + a_6, + get_word_row(new_word_idx - 16) + 1, + )?; + + // Copy sigma_1(W_{i - 2}) + lower_sigma_1_v2_results[new_word_idx - 16].0.copy_advice( + || format!("sigma_1(W_{})_lo", new_word_idx - 2), + region, + a_7, + get_word_row(new_word_idx - 16), + )?; + lower_sigma_1_v2_results[new_word_idx - 16].1.copy_advice( + || format!("sigma_1(W_{})_hi", new_word_idx - 2), + region, + a_7, + get_word_row(new_word_idx - 16) + 1, + )?; + + // Copy W_{i - 7} + w_halves[new_word_idx - 7].0.copy_advice( + || format!("W_{}_lo", new_word_idx - 7), + region, + a_8, + get_word_row(new_word_idx - 16), + )?; + w_halves[new_word_idx - 7].1.copy_advice( + || format!("W_{}_hi", new_word_idx - 7), + region, + a_8, + get_word_row(new_word_idx - 16) + 1, + )?; + + // Calculate W_i, carry_i + let (word, carry) = sum_with_carry(vec![ + ( + lower_sigma_1_v2_results[new_word_idx - 16].0.value_u16(), + lower_sigma_1_v2_results[new_word_idx - 16].1.value_u16(), + ), + ( + w_halves[new_word_idx - 7].0.value_u16(), + w_halves[new_word_idx - 7].1.value_u16(), + ), + (sigma_0_output.0.value_u16(), sigma_0_output.1.value_u16()), + ( + w_halves[new_word_idx - 16].0.value_u16(), + w_halves[new_word_idx - 16].1.value_u16(), + ), + ]); + + // Assign W_i, carry_i + region.assign_advice( + || format!("W_{new_word_idx}"), + a_5, + get_word_row(new_word_idx - 16) + 1, + || word.map(|word| F::from(word as u64)), + )?; + region.assign_advice( + || format!("carry_{new_word_idx}"), + a_9, + get_word_row(new_word_idx - 16) + 1, + || carry.map(|carry| F::from(carry)), + )?; + let (word, halves) = self.assign_word_and_halves(region, word, new_word_idx)?; + w.push(MessageWord(word)); + w_halves.push(halves); + + Ok(lower_sigma_0_v2_results.clone()) + }; + + let mut tmp_lower_sigma_0_v2_results: Vec<(AssignedBits<_, 16>, AssignedBits<_, 16>)> = Vec::with_capacity(SUBREGION_2_LEN); // Use up all the output from Subregion 1 lower_sigma_0 @@ -288,12 +292,12 @@ impl MessageScheduleConfig { } /// Pieces of length [3, 4, 3, 7, 1, 1, 13] - fn decompose_word( + fn decompose_word( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, word: Value<&Bits<32>>, index: usize, - ) -> Result { + ) -> Result, Error> { let row = get_word_row(index); let pieces = word.map(|word| { @@ -314,24 +318,24 @@ impl MessageScheduleConfig { let a_4 = self.extras[1]; // Assign `a` (3-bit piece) - let a = AssignedBits::<3>::assign_bits(region, || "a", a_3, row - 1, pieces[0].clone())?; + let a = AssignedBits::<_, 3>::assign_bits(region, || "a", a_3, row - 1, pieces[0].clone())?; // Assign `b` (4-bit piece) lookup let spread_b: Value> = pieces[1].clone().map(SpreadWord::try_new); let spread_b = SpreadVar::with_lookup(region, &self.lookup, row + 1, spread_b)?; // Assign `c` (3-bit piece) - let c = AssignedBits::<3>::assign_bits(region, || "c", a_4, row - 1, pieces[2].clone())?; + let c = AssignedBits::<_, 3>::assign_bits(region, || "c", a_4, row - 1, pieces[2].clone())?; // Assign `d` (7-bit piece) lookup let spread_d: Value> = pieces[3].clone().map(SpreadWord::try_new); let spread_d = SpreadVar::with_lookup(region, &self.lookup, row, spread_d)?; // Assign `e` (1-bit piece) - let e = AssignedBits::<1>::assign_bits(region, || "e", a_3, row + 1, pieces[4].clone())?; + let e = AssignedBits::<_, 1>::assign_bits(region, || "e", a_3, row + 1, pieces[4].clone())?; // Assign `f` (1-bit piece) - let f = AssignedBits::<1>::assign_bits(region, || "f", a_4, row + 1, pieces[5].clone())?; + let f = AssignedBits::<_, 1>::assign_bits(region, || "f", a_4, row + 1, pieces[5].clone())?; // Assign `g` (13-bit piece) lookup let spread_g = pieces[6].clone().map(SpreadWord::try_new); @@ -354,11 +358,11 @@ impl MessageScheduleConfig { /// A word in subregion 2 /// (3, 4, 3, 7, 1, 1, 13)-bit chunks #[allow(clippy::type_complexity)] - fn assign_lower_sigma_v2_pieces( + fn assign_lower_sigma_v2_pieces( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, row: usize, - word: &Subregion2Word, + word: &Subregion2Word, ) -> Result<(), Error> { let a_3 = self.extras[0]; let a_4 = self.extras[1]; @@ -370,7 +374,7 @@ impl MessageScheduleConfig { word.a.copy_advice(|| "a", region, a_3, row + 1)?; // Witness `spread_a` - AssignedBits::<6>::assign_bits(region, || "spread_a", a_4, row + 1, word.spread_a())?; + AssignedBits::<_, 6>::assign_bits(region, || "spread_a", a_4, row + 1, word.spread_a())?; // Split `b` (4-bit chunk) into `b_hi` and `b_lo` // Assign `b_lo`, `spread_b_lo` @@ -378,9 +382,9 @@ impl MessageScheduleConfig { let b_lo: Value<[bool; 2]> = word.b.value().map(|b| b.0[..2].try_into().unwrap()); let spread_b_lo = b_lo.map(spread_bits); { - AssignedBits::<2>::assign_bits(region, || "b_lo", a_3, row - 1, b_lo)?; + AssignedBits::<_, 2>::assign_bits(region, || "b_lo", a_3, row - 1, b_lo)?; - AssignedBits::<4>::assign_bits(region, || "spread_b_lo", a_4, row - 1, spread_b_lo)?; + AssignedBits::<_, 4>::assign_bits(region, || "spread_b_lo", a_4, row - 1, spread_b_lo)?; }; // Split `b` (2-bit chunk) into `b_hi` and `b_lo` @@ -388,9 +392,9 @@ impl MessageScheduleConfig { let b_hi: Value<[bool; 2]> = word.b.value().map(|b| b.0[2..].try_into().unwrap()); let spread_b_hi = b_hi.map(spread_bits); { - AssignedBits::<2>::assign_bits(region, || "b_hi", a_5, row - 1, b_hi)?; + AssignedBits::<_, 2>::assign_bits(region, || "b_hi", a_5, row - 1, b_hi)?; - AssignedBits::<4>::assign_bits(region, || "spread_b_hi", a_6, row - 1, spread_b_hi)?; + AssignedBits::<_, 4>::assign_bits(region, || "spread_b_hi", a_6, row - 1, spread_b_hi)?; }; // Assign `b` and copy constraint @@ -400,7 +404,7 @@ impl MessageScheduleConfig { word.c.copy_advice(|| "c", region, a_5, row + 1)?; // Witness `spread_c` - AssignedBits::<6>::assign_bits(region, || "spread_c", a_6, row + 1, word.spread_c())?; + AssignedBits::<_, 6>::assign_bits(region, || "spread_c", a_6, row + 1, word.spread_c())?; // Assign `spread_d` and copy constraint word.spread_d.copy_advice(|| "spread_d", region, a_4, row)?; @@ -417,11 +421,11 @@ impl MessageScheduleConfig { Ok(()) } - fn lower_sigma_0_v2( + fn lower_sigma_0_v2( &self, - region: &mut Region<'_, pallas::Base>, - word: Subregion2Word, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + region: &mut Region<'_, F>, + word: Subregion2Word, + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let row = get_word_row(word.index) + 3; @@ -450,11 +454,11 @@ impl MessageScheduleConfig { ) } - fn lower_sigma_1_v2( + fn lower_sigma_1_v2( &self, - region: &mut Region<'_, pallas::Base>, - word: Subregion2Word, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + region: &mut Region<'_, F>, + word: Subregion2Word, + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let row = get_word_row(word.index) + SIGMA_0_V2_ROWS + 3; diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs index b23046e42e..9f2217c7c1 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion3.rs @@ -1,27 +1,30 @@ -use super::super::{util::*, AssignedBits, Bits, SpreadVar, SpreadWord, Table16Assignment}; -use super::{schedule_util::*, MessageScheduleConfig, MessageWord}; +use super::super::Field; +use super::{ + super::{util::*, AssignedBits, Bits, SpreadVar, SpreadWord, Table16Assignment}, + schedule_util::*, + MessageScheduleConfig, MessageWord, +}; use halo2_proofs::{ circuit::{Region, Value}, plonk::Error, }; -use halo2curves::pasta::pallas; use std::convert::TryInto; // A word in subregion 3 // (10, 7, 2, 13)-bit chunks -pub struct Subregion3Word { +pub struct Subregion3Word { index: usize, #[allow(dead_code)] - a: AssignedBits<10>, - b: AssignedBits<7>, - c: AssignedBits<2>, + a: AssignedBits, + b: AssignedBits, + c: AssignedBits, #[allow(dead_code)] - d: AssignedBits<13>, - spread_a: AssignedBits<20>, - spread_d: AssignedBits<26>, + d: AssignedBits, + spread_a: AssignedBits, + spread_d: AssignedBits, } -impl Subregion3Word { +impl Subregion3Word { fn spread_a(&self) -> Value<[bool; 20]> { self.spread_a.value().map(|v| v.0) } @@ -78,12 +81,12 @@ impl Subregion3Word { impl MessageScheduleConfig { // W_[49..62] - pub fn assign_subregion3( + pub fn assign_subregion3( &self, - region: &mut Region<'_, pallas::Base>, - lower_sigma_0_v2_output: Vec<(AssignedBits<16>, AssignedBits<16>)>, - w: &mut Vec, - w_halves: &mut Vec<(AssignedBits<16>, AssignedBits<16>)>, + region: &mut Region<'_, F>, + lower_sigma_0_v2_output: Vec<(AssignedBits, AssignedBits)>, + w: &mut Vec>, + w_halves: &mut Vec<(AssignedBits, AssignedBits)>, ) -> Result<(), Error> { let a_5 = self.message_schedule; let a_6 = self.extras[2]; @@ -168,16 +171,16 @@ impl MessageScheduleConfig { // Assign W_i, carry_i region.assign_advice( - || format!("W_{}", new_word_idx), + || format!("W_{new_word_idx}"), a_5, get_word_row(new_word_idx - 16) + 1, - || word.map(|word| pallas::Base::from(word as u64)), + || word.map(|word| F::from(word as u64)), )?; region.assign_advice( - || format!("carry_{}", new_word_idx), + || format!("carry_{new_word_idx}"), a_9, get_word_row(new_word_idx - 16) + 1, - || carry.map(|carry| pallas::Base::from(carry as u64)), + || carry.map(|carry| F::from(carry)), )?; let (word, halves) = self.assign_word_and_halves(region, word, new_word_idx)?; w.push(MessageWord(word)); @@ -194,12 +197,12 @@ impl MessageScheduleConfig { } /// Pieces of length [10, 7, 2, 13] - fn decompose_subregion3_word( + fn decompose_subregion3_word( &self, - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, word: Value<&Bits<32>>, index: usize, - ) -> Result { + ) -> Result, Error> { let row = get_word_row(index); // Rename these here for ease of matching the gates to the specification. @@ -221,10 +224,10 @@ impl MessageScheduleConfig { let spread_a = SpreadVar::with_lookup(region, &self.lookup, row + 1, spread_a)?; // Assign `b` (7-bit piece) - let b = AssignedBits::<7>::assign_bits(region, || "b", a_4, row + 1, pieces[1].clone())?; + let b = AssignedBits::::assign_bits(region, || "b", a_4, row + 1, pieces[1].clone())?; // Assign `c` (2-bit piece) - let c = AssignedBits::<2>::assign_bits(region, || "c", a_3, row + 1, pieces[2].clone())?; + let c = AssignedBits::::assign_bits(region, || "c", a_3, row + 1, pieces[2].clone())?; // Assign `d` (13-bit piece) lookup let spread_d = pieces[3].clone().map(SpreadWord::try_new); @@ -241,11 +244,11 @@ impl MessageScheduleConfig { }) } - fn lower_sigma_1( + fn lower_sigma_1( &self, - region: &mut Region<'_, pallas::Base>, - word: Subregion3Word, - ) -> Result<(AssignedBits<16>, AssignedBits<16>), Error> { + region: &mut Region<'_, F>, + word: Subregion3Word, + ) -> Result<(AssignedBits, AssignedBits), Error> { let a_3 = self.extras[0]; let a_4 = self.extras[1]; let a_5 = self.message_schedule; @@ -289,7 +292,7 @@ impl MessageScheduleConfig { // Witness `spread_c` { let spread_c = word.c.value().map(spread_bits); - AssignedBits::<4>::assign_bits(region, || "spread_c", a_4, row + 1, spread_c)?; + AssignedBits::::assign_bits(region, || "spread_c", a_4, row + 1, spread_c)?; } // Assign `spread_d` and copy constraint diff --git a/halo2_gadgets/src/sha256/table16/spread_table.rs b/halo2_gadgets/src/sha256/table16/spread_table.rs index 3e1488e9ac..471a844f59 100644 --- a/halo2_gadgets/src/sha256/table16/spread_table.rs +++ b/halo2_gadgets/src/sha256/table16/spread_table.rs @@ -1,13 +1,10 @@ -use super::{util::*, AssignedBits}; +use super::{util::*, AssignedBits, Field}; use halo2_proofs::{ arithmetic::FieldExt, circuit::{Chip, Layouter, Region, Value}, plonk::{Advice, Column, ConstraintSystem, Error, TableColumn}, - poly::Rotation, }; -use halo2curves::pasta::pallas; -use std::convert::TryInto; -use std::marker::PhantomData; +use std::{convert::TryInto, marker::PhantomData}; const BITS_7: usize = 1 << 7; const BITS_10: usize = 1 << 10; @@ -67,15 +64,15 @@ impl SpreadWord { /// A variable stored in advice columns corresponding to a row of [`SpreadTableConfig`]. #[derive(Clone, Debug)] -pub(super) struct SpreadVar { +pub(super) struct SpreadVar { pub tag: Value, - pub dense: AssignedBits, - pub spread: AssignedBits, + pub dense: AssignedBits, + pub spread: AssignedBits, } -impl SpreadVar { +impl SpreadVar { pub(super) fn with_lookup( - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, cols: &SpreadInputs, row: usize, word: Value>, @@ -88,20 +85,25 @@ impl SpreadVar { || "tag", cols.tag, row, - || tag.map(|tag| pallas::Base::from(tag as u64)), + || tag.map(|tag| F::from(tag as u64)), )?; let dense = - AssignedBits::::assign_bits(region, || "dense", cols.dense, row, dense_val)?; + AssignedBits::<_, DENSE>::assign_bits(region, || "dense", cols.dense, row, dense_val)?; - let spread = - AssignedBits::::assign_bits(region, || "spread", cols.spread, row, spread_val)?; + let spread = AssignedBits::<_, SPREAD>::assign_bits( + region, + || "spread", + cols.spread, + row, + spread_val, + )?; Ok(SpreadVar { tag, dense, spread }) } pub(super) fn without_lookup( - region: &mut Region<'_, pallas::Base>, + region: &mut Region<'_, F>, dense_col: Column, dense_row: usize, spread_col: Column, @@ -112,7 +114,7 @@ impl SpreadVar { let dense_val = word.map(|word| word.dense); let spread_val = word.map(|word| word.spread); - let dense = AssignedBits::::assign_bits( + let dense = AssignedBits::<_, DENSE>::assign_bits( region, || "dense", dense_col, @@ -120,7 +122,7 @@ impl SpreadVar { dense_val, )?; - let spread = AssignedBits::::assign_bits( + let spread = AssignedBits::<_, SPREAD>::assign_bits( region, || "spread", spread_col, @@ -183,6 +185,7 @@ impl SpreadTableChip { let table_spread = meta.lookup_table_column(); meta.lookup("lookup", |meta| { + use halo2_proofs::poly::Rotation; let tag_cur = meta.query_advice(input_tag, Rotation::cur()); let dense_cur = meta.query_advice(input_dense, Rotation::cur()); let spread_cur = meta.query_advice(input_spread, Rotation::cur()); @@ -441,7 +444,7 @@ mod tests { let prover = match MockProver::::run(17, &circuit, vec![]) { Ok(prover) => prover, - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; assert_eq!(prover.verify(), Ok(())); } diff --git a/halo2_gadgets/src/sha256/table16/util.rs b/halo2_gadgets/src/sha256/table16/util.rs index 6a790d3797..d3da5317ca 100644 --- a/halo2_gadgets/src/sha256/table16/util.rs +++ b/halo2_gadgets/src/sha256/table16/util.rs @@ -110,7 +110,7 @@ pub fn sum_with_carry(words: Vec<(Value, Value)>) -> (Value, Valu sum_lo.zip(sum_hi).map(|(lo, hi)| lo + (1 << 16) * hi) }; - let carry = sum.map(|sum| (sum >> 32) as u64); + let carry = sum.map(|sum| (sum >> 32)); let sum = sum.map(|sum| sum as u32); (sum, carry) From c8f214e30acc6ece1d49b12573a531a6d64b7b21 Mon Sep 17 00:00:00 2001 From: Ho Vei Date: Thu, 30 Nov 2023 11:28:12 +0800 Subject: [PATCH 2/2] fix clippy --- halo2_gadgets/benches/sha256.rs | 2 +- halo2_gadgets/src/sha256/table16/compression.rs | 1 + .../src/sha256/table16/compression/compression_util.rs | 1 + .../src/sha256/table16/message_schedule/schedule_util.rs | 1 + halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs | 2 ++ halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/halo2_gadgets/benches/sha256.rs b/halo2_gadgets/benches/sha256.rs index 670956cb0d..a702e84ebe 100644 --- a/halo2_gadgets/benches/sha256.rs +++ b/halo2_gadgets/benches/sha256.rs @@ -52,7 +52,7 @@ fn bench(name: &str, k: u32, c: &mut Criterion) { mut layouter: impl Layouter, ) -> Result<(), Error> { Table16Chip::load(config.clone(), &mut layouter)?; - let table16_chip = Table16Chip::construct(config); + let table16_chip = Table16Chip::construct::(config); // Test vector: "abc" let test_input = [ diff --git a/halo2_gadgets/src/sha256/table16/compression.rs b/halo2_gadgets/src/sha256/table16/compression.rs index 1204d2332b..9c2de95034 100644 --- a/halo2_gadgets/src/sha256/table16/compression.rs +++ b/halo2_gadgets/src/sha256/table16/compression.rs @@ -427,6 +427,7 @@ impl State { } } + #[allow(clippy::type_complexity)] pub fn decompose( self, ) -> ( diff --git a/halo2_gadgets/src/sha256/table16/compression/compression_util.rs b/halo2_gadgets/src/sha256/table16/compression/compression_util.rs index 18666a7b41..caa0fd7c5f 100644 --- a/halo2_gadgets/src/sha256/table16/compression/compression_util.rs +++ b/halo2_gadgets/src/sha256/table16/compression/compression_util.rs @@ -941,6 +941,7 @@ impl CompressionConfig { } #[allow(clippy::many_single_char_names)] +#[allow(clippy::type_complexity)] pub fn match_state( state: State, ) -> ( diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs index 6c092dc361..3aab76e6fa 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/schedule_util.rs @@ -146,6 +146,7 @@ pub const MSG_SCHEDULE_TEST_OUTPUT: [u32; ROUNDS] = [ impl MessageScheduleConfig { // Assign a word and its hi and lo halves + #[allow(clippy::type_complexity)] pub fn assign_word_and_halves( &self, region: &mut Region<'_, F>, diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs index 2fa0474881..a5bed0b062 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion1.rs @@ -78,6 +78,7 @@ impl Subregion1Word { } impl MessageScheduleConfig { + #[allow(clippy::type_complexity)] pub fn assign_subregion1( &self, region: &mut Region<'_, F>, @@ -104,6 +105,7 @@ impl MessageScheduleConfig { } /// Pieces of length [3, 4, 11, 14] + #[allow(clippy::type_complexity)] fn decompose_subregion1_word( &self, region: &mut Region<'_, F>, diff --git a/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs b/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs index 18386995c5..e34c4bd3a2 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule/subregion2.rs @@ -156,6 +156,7 @@ impl Subregion2Word { impl MessageScheduleConfig { // W_[14..49] + #[allow(clippy::type_complexity)] pub fn assign_subregion2( &self, region: &mut Region<'_, F>,