|
1 | 1 | //! WARNING: the order of fields in the structs is important, do not change it
|
2 | 2 |
|
3 |
| -use openvm_circuit_primitives::{utils::not, AlignedBorrow}; |
| 3 | +use openvm_circuit_primitives::utils::not; |
| 4 | +use openvm_circuit_primitives_derive::ColsRef; |
4 | 5 | use openvm_stark_backend::p3_field::FieldAlgebra;
|
5 | 6 |
|
6 |
| -use super::{ |
7 |
| - SHA256_HASH_WORDS, SHA256_ROUNDS_PER_ROW, SHA256_ROW_VAR_CNT, SHA256_WORD_BITS, |
8 |
| - SHA256_WORD_U16S, SHA256_WORD_U8S, |
9 |
| -}; |
| 7 | +use crate::Sha2Config; |
10 | 8 |
|
11 |
| -/// In each SHA256 block: |
12 |
| -/// - First 16 rows use Sha256RoundCols |
13 |
| -/// - Final row uses Sha256DigestCols |
| 9 | +/// In each SHA block: |
| 10 | +/// - First C::ROUND_ROWS rows use ShaRoundCols |
| 11 | +/// - Final row uses ShaDigestCols |
14 | 12 | ///
|
15 |
| -/// Note that for soundness, we require that there is always a padding row after the last digest row in the trace. |
16 |
| -/// Right now, this is true because the unpadded height is a multiple of 17, and thus not a power of 2. |
17 |
| -/// |
18 |
| -/// Sha256RoundCols and Sha256DigestCols share the same first 3 fields: |
| 13 | +/// ShaRoundCols and ShaDigestCols share the same first 3 fields: |
19 | 14 | /// - flags
|
20 | 15 | /// - work_vars/hash (same type, different name)
|
21 | 16 | /// - schedule_helper
|
22 | 17 | ///
|
23 | 18 | /// This design allows for:
|
24 | 19 | /// 1. Common constraints to work on either struct type by accessing these shared fields
|
25 | 20 | /// 2. Specific constraints to use the appropriate struct, with flags helping to do conditional constraints
|
26 |
| -/// |
27 |
| -/// Note that the `Sha256WorkVarsCols` field it is used for different purposes in the two structs. |
28 | 21 | #[repr(C)]
|
29 |
| -#[derive(Clone, Copy, Debug, AlignedBorrow)] |
30 |
| -pub struct Sha256RoundCols<T> { |
31 |
| - pub flags: Sha256FlagsCols<T>, |
32 |
| - /// Stores the current state of the working variables |
33 |
| - pub work_vars: Sha256WorkVarsCols<T>, |
34 |
| - pub schedule_helper: Sha256MessageHelperCols<T>, |
35 |
| - pub message_schedule: Sha256MessageScheduleCols<T>, |
| 22 | +#[derive(Clone, Copy, Debug, ColsRef)] |
| 23 | +#[config(Sha2Config)] |
| 24 | +pub struct ShaRoundCols< |
| 25 | + T, |
| 26 | + const WORD_BITS: usize, |
| 27 | + const WORD_U8S: usize, |
| 28 | + const WORD_U16S: usize, |
| 29 | + const ROUNDS_PER_ROW: usize, |
| 30 | + const ROUNDS_PER_ROW_MINUS_ONE: usize, |
| 31 | + const ROW_VAR_CNT: usize, |
| 32 | +> { |
| 33 | + pub flags: Sha2FlagsCols<T, ROW_VAR_CNT>, |
| 34 | + pub work_vars: ShaWorkVarsCols<T, WORD_BITS, ROUNDS_PER_ROW, WORD_U16S>, |
| 35 | + pub schedule_helper: |
| 36 | + Sha2MessageHelperCols<T, WORD_U16S, ROUNDS_PER_ROW, ROUNDS_PER_ROW_MINUS_ONE>, |
| 37 | + pub message_schedule: ShaMessageScheduleCols<T, WORD_BITS, ROUNDS_PER_ROW, WORD_U8S>, |
36 | 38 | }
|
37 | 39 |
|
38 | 40 | #[repr(C)]
|
39 |
| -#[derive(Clone, Copy, Debug, AlignedBorrow)] |
40 |
| -pub struct Sha256DigestCols<T> { |
41 |
| - pub flags: Sha256FlagsCols<T>, |
42 |
| - /// Will serve as previous hash values for the next block. |
43 |
| - /// - on non-last blocks, this is the final hash of the current block |
44 |
| - /// - on last blocks, this is the initial state constants, SHA256_H. |
45 |
| - /// The work variables constraints are applied on all rows, so `carry_a` and `carry_e` |
46 |
| - /// must be filled in with dummy values to ensure these constraints hold. |
47 |
| - pub hash: Sha256WorkVarsCols<T>, |
48 |
| - pub schedule_helper: Sha256MessageHelperCols<T>, |
| 41 | +#[derive(Clone, Copy, Debug, ColsRef)] |
| 42 | +#[config(Sha2Config)] |
| 43 | +pub struct ShaDigestCols< |
| 44 | + T, |
| 45 | + const WORD_BITS: usize, |
| 46 | + const WORD_U8S: usize, |
| 47 | + const WORD_U16S: usize, |
| 48 | + const HASH_WORDS: usize, |
| 49 | + const ROUNDS_PER_ROW: usize, |
| 50 | + const ROUNDS_PER_ROW_MINUS_ONE: usize, |
| 51 | + const ROW_VAR_CNT: usize, |
| 52 | +> { |
| 53 | + pub flags: Sha2FlagsCols<T, ROW_VAR_CNT>, |
| 54 | + /// Will serve as previous hash values for the next block |
| 55 | + pub hash: ShaWorkVarsCols<T, WORD_BITS, ROUNDS_PER_ROW, WORD_U16S>, |
| 56 | + pub schedule_helper: |
| 57 | + Sha2MessageHelperCols<T, WORD_U16S, ROUNDS_PER_ROW, ROUNDS_PER_ROW_MINUS_ONE>, |
49 | 58 | /// The actual final hash values of the given block
|
50 | 59 | /// Note: the above `hash` will be equal to `final_hash` unless we are on the last block
|
51 |
| - pub final_hash: [[T; SHA256_WORD_U8S]; SHA256_HASH_WORDS], |
| 60 | + pub final_hash: [[T; WORD_U8S]; HASH_WORDS], |
52 | 61 | /// The final hash of the previous block
|
53 | 62 | /// Note: will be constrained using interactions with the chip itself
|
54 |
| - pub prev_hash: [[T; SHA256_WORD_U16S]; SHA256_HASH_WORDS], |
| 63 | + pub prev_hash: [[T; WORD_U16S]; HASH_WORDS], |
55 | 64 | }
|
56 | 65 |
|
57 | 66 | #[repr(C)]
|
58 |
| -#[derive(Clone, Copy, Debug, AlignedBorrow)] |
59 |
| -pub struct Sha256MessageScheduleCols<T> { |
| 67 | +#[derive(Clone, Copy, Debug, ColsRef)] |
| 68 | +#[config(Sha2Config)] |
| 69 | +pub struct ShaMessageScheduleCols< |
| 70 | + T, |
| 71 | + const WORD_BITS: usize, |
| 72 | + const ROUNDS_PER_ROW: usize, |
| 73 | + const WORD_U8S: usize, |
| 74 | +> { |
60 | 75 | /// The message schedule words as 32-bit integers
|
61 |
| - /// The first 16 words will be the message data |
62 |
| - pub w: [[T; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW], |
63 |
| - /// Will be message schedule carries for rows 4..16 and a buffer for rows 0..4 to be used freely by wrapper chips |
64 |
| - /// Note: carries are 2 bit numbers represented using 2 cells as individual bits |
65 |
| - pub carry_or_buffer: [[T; SHA256_WORD_U8S]; SHA256_ROUNDS_PER_ROW], |
| 76 | + pub w: [[T; WORD_BITS]; ROUNDS_PER_ROW], |
| 77 | + /// Will be message schedule carries for rows 4..C::ROUND_ROWS and a buffer for rows 0..4 to be used freely by wrapper chips |
| 78 | + /// Note: carries are represented as 2 bit numbers |
| 79 | + pub carry_or_buffer: [[T; WORD_U8S]; ROUNDS_PER_ROW], |
66 | 80 | }
|
67 | 81 |
|
68 | 82 | #[repr(C)]
|
69 |
| -#[derive(Clone, Copy, Debug, AlignedBorrow)] |
70 |
| -pub struct Sha256WorkVarsCols<T> { |
| 83 | +#[derive(Clone, Copy, Debug, ColsRef)] |
| 84 | +#[config(Sha2Config)] |
| 85 | +pub struct ShaWorkVarsCols< |
| 86 | + T, |
| 87 | + const WORD_BITS: usize, |
| 88 | + const ROUNDS_PER_ROW: usize, |
| 89 | + const WORD_U16S: usize, |
| 90 | +> { |
71 | 91 | /// `a` and `e` after each iteration as 32-bits
|
72 |
| - pub a: [[T; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW], |
73 |
| - pub e: [[T; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW], |
| 92 | + pub a: [[T; WORD_BITS]; ROUNDS_PER_ROW], |
| 93 | + pub e: [[T; WORD_BITS]; ROUNDS_PER_ROW], |
74 | 94 | /// The carry's used for addition during each iteration when computing `a` and `e`
|
75 |
| - pub carry_a: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], |
76 |
| - pub carry_e: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], |
| 95 | + pub carry_a: [[T; WORD_U16S]; ROUNDS_PER_ROW], |
| 96 | + pub carry_e: [[T; WORD_U16S]; ROUNDS_PER_ROW], |
77 | 97 | }
|
78 | 98 |
|
79 | 99 | /// These are the columns that are used to help with the message schedule additions
|
80 | 100 | /// Note: these need to be correctly assigned for every row even on padding rows
|
81 | 101 | #[repr(C)]
|
82 |
| -#[derive(Clone, Copy, Debug, AlignedBorrow)] |
83 |
| -pub struct Sha256MessageHelperCols<T> { |
| 102 | +#[derive(Clone, Copy, Debug, ColsRef)] |
| 103 | +#[config(Sha2Config)] |
| 104 | +pub struct Sha2MessageHelperCols< |
| 105 | + T, |
| 106 | + const WORD_U16S: usize, |
| 107 | + const ROUNDS_PER_ROW: usize, |
| 108 | + const ROUNDS_PER_ROW_MINUS_ONE: usize, |
| 109 | +> { |
84 | 110 | /// The following are used to move data forward to constrain the message schedule additions
|
85 |
| - /// The value of `w` (message schedule word) from 3 rounds ago |
86 |
| - /// In general, `w_i` means `w` from `i` rounds ago |
87 |
| - pub w_3: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW - 1], |
| 111 | + /// The value of `w` from 3 rounds ago |
| 112 | + pub w_3: [[T; WORD_U16S]; ROUNDS_PER_ROW_MINUS_ONE], |
88 | 113 | /// Here intermediate(i) = w_i + sig_0(w_{i+1})
|
89 | 114 | /// Intermed_t represents the intermediate t rounds ago
|
90 |
| - /// This is needed to constrain the message schedule, since we can only constrain on two rows at a time |
91 |
| - pub intermed_4: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], |
92 |
| - pub intermed_8: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], |
93 |
| - pub intermed_12: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], |
| 115 | + pub intermed_4: [[T; WORD_U16S]; ROUNDS_PER_ROW], |
| 116 | + pub intermed_8: [[T; WORD_U16S]; ROUNDS_PER_ROW], |
| 117 | + pub intermed_12: [[T; WORD_U16S]; ROUNDS_PER_ROW], |
94 | 118 | }
|
95 | 119 |
|
96 | 120 | #[repr(C)]
|
97 |
| -#[derive(Clone, Copy, Debug, AlignedBorrow)] |
98 |
| -pub struct Sha256FlagsCols<T> { |
99 |
| - /// A flag that indicates if the current row is among the first 16 rows of a block. |
| 121 | +#[derive(Clone, Copy, Debug, ColsRef)] |
| 122 | +#[config(Sha2Config)] |
| 123 | +pub struct Sha2FlagsCols<T, const ROW_VAR_CNT: usize> { |
100 | 124 | pub is_round_row: T,
|
101 |
| - /// A flag that indicates if the current row is among the first 4 rows of a block. |
| 125 | + /// A flag that indicates if the current row is among the first 4 rows of a block (the message rows) |
102 | 126 | pub is_first_4_rows: T,
|
103 |
| - /// A flag that indicates if the current row is the last (17th) row of a block. |
104 | 127 | pub is_digest_row: T,
|
105 |
| - // A flag that indicates if the current row is the last block of the message. |
106 |
| - // This flag is only used in digest rows. |
107 | 128 | pub is_last_block: T,
|
108 | 129 | /// We will encode the row index [0..17) using 5 cells
|
109 |
| - pub row_idx: [T; SHA256_ROW_VAR_CNT], |
110 |
| - /// The index of the current block in the trace starting at 1. |
111 |
| - /// Set to 0 on padding rows. |
| 130 | + pub row_idx: [T; ROW_VAR_CNT], |
| 131 | + /// The global index of the current block |
112 | 132 | pub global_block_idx: T,
|
113 |
| - /// The index of the current block in the current message starting at 0. |
114 |
| - /// Resets after every message. |
115 |
| - /// Set to 0 on padding rows. |
| 133 | + /// Will store the index of the current block in the current message starting from 0 |
116 | 134 | pub local_block_idx: T,
|
117 | 135 | }
|
118 | 136 |
|
119 |
| -impl<O, T: Copy + core::ops::Add<Output = O>> Sha256FlagsCols<T> { |
120 |
| - // This refers to the padding rows that are added to the air to make the trace length a power of 2. |
121 |
| - // Not to be confused with the padding added to messages as part of the SHA hash function. |
| 137 | +impl<O, T: Copy + core::ops::Add<Output = O>, const ROW_VAR_CNT: usize> |
| 138 | + Sha2FlagsCols<T, ROW_VAR_CNT> |
| 139 | +{ |
122 | 140 | pub fn is_not_padding_row(&self) -> O {
|
123 | 141 | self.is_round_row + self.is_digest_row
|
124 | 142 | }
|
125 | 143 |
|
126 |
| - // This refers to the padding rows that are added to the air to make the trace length a power of 2. |
127 |
| - // Not to be confused with the padding added to messages as part of the SHA hash function. |
| 144 | + pub fn is_padding_row(&self) -> O |
| 145 | + where |
| 146 | + O: FieldAlgebra, |
| 147 | + { |
| 148 | + not(self.is_not_padding_row()) |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +impl<O, T: Copy + core::ops::Add<Output = O>> Sha2FlagsColsRef<'_, T> { |
| 153 | + pub fn is_not_padding_row(&self) -> O { |
| 154 | + *self.is_round_row + *self.is_digest_row |
| 155 | + } |
| 156 | + |
128 | 157 | pub fn is_padding_row(&self) -> O
|
129 | 158 | where
|
130 | 159 | O: FieldAlgebra,
|
|
0 commit comments