@@ -37,7 +37,7 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
37
37
pub fn new ( bitwise_lookup_bus : BitwiseOperationLookupBus , self_bus_idx : BusIndex ) -> Self {
38
38
Self {
39
39
bitwise_lookup_bus,
40
- row_idx_encoder : Encoder :: new ( 18 , 2 , false ) ,
40
+ row_idx_encoder : Encoder :: new ( C :: ROWS_PER_BLOCK + 1 , 2 , false ) , // + 1 for dummy (padding) rows
41
41
bus : PermutationCheckBus :: new ( self_bus_idx) ,
42
42
_phantom : PhantomData ,
43
43
}
@@ -91,29 +91,35 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
91
91
92
92
self . row_idx_encoder
93
93
. eval ( builder, local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) ) ;
94
- builder. assert_one (
95
- self . row_idx_encoder
96
- . contains_flag_range :: < AB > ( local_cols . flags . row_idx . to_slice ( ) . unwrap ( ) , 0 ..=17 ) ,
97
- ) ;
94
+ builder. assert_one ( self . row_idx_encoder . contains_flag_range :: < AB > (
95
+ local_cols . flags . row_idx . to_slice ( ) . unwrap ( ) ,
96
+ 0 ..=C :: ROWS_PER_BLOCK ,
97
+ ) ) ;
98
98
builder. assert_eq (
99
99
self . row_idx_encoder
100
100
. contains_flag_range :: < AB > ( local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) , 0 ..=3 ) ,
101
101
* flags. is_first_4_rows ,
102
102
) ;
103
103
builder. assert_eq (
104
- self . row_idx_encoder
105
- . contains_flag_range :: < AB > ( local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) , 0 ..=15 ) ,
104
+ self . row_idx_encoder . contains_flag_range :: < AB > (
105
+ local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) ,
106
+ 0 ..=C :: ROUND_ROWS - 1 ,
107
+ ) ,
106
108
* flags. is_round_row ,
107
109
) ;
108
110
builder. assert_eq (
109
- self . row_idx_encoder
110
- . contains_flag :: < AB > ( local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) , & [ 16 ] ) ,
111
+ self . row_idx_encoder . contains_flag :: < AB > (
112
+ local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) ,
113
+ & [ C :: ROUND_ROWS ] ,
114
+ ) ,
111
115
* flags. is_digest_row ,
112
116
) ;
113
- // If padding row we want the row_idx to be 17
117
+ // If padding row we want the row_idx to be C::ROWS_PER_BLOCK
114
118
builder. assert_eq (
115
- self . row_idx_encoder
116
- . contains_flag :: < AB > ( local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) , & [ 17 ] ) ,
119
+ self . row_idx_encoder . contains_flag :: < AB > (
120
+ local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) ,
121
+ & [ C :: ROWS_PER_BLOCK ] ,
122
+ ) ,
117
123
flags. is_padding_row ( ) ,
118
124
) ;
119
125
@@ -130,14 +136,14 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
130
136
/// Implements constraints for a digest row that ensure proper state transitions between blocks
131
137
/// This validates that:
132
138
/// The work variables are correctly initialized for the next message block
133
- /// For the last message block, the initial state matches SHA256_H constants
139
+ /// For the last message block, the initial state matches SHA_H constants
134
140
fn eval_digest_row < AB : InteractionBuilder > (
135
141
& self ,
136
142
builder : & mut AB ,
137
143
local : ShaRoundColsRef < AB :: Var > ,
138
144
next : ShaDigestColsRef < AB :: Var > ,
139
145
) {
140
- // Check that if this is the last row of a message or an inpadding row, the hash should be the [SHA256_H ]
146
+ // Check that if this is the last row of a message or an inpadding row, the hash should be the [SHA_H ]
141
147
for i in 0 ..C :: ROUNDS_PER_ROW {
142
148
let a = next. hash . a . row ( i) . mapv ( |x| x. into ( ) ) . to_vec ( ) ;
143
149
let e = next. hash . e . row ( i) . mapv ( |x| x. into ( ) ) . to_vec ( ) ;
@@ -146,7 +152,7 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
146
152
let a_limb = compose :: < AB :: Expr > ( & a[ j * 16 ..( j + 1 ) * 16 ] , 1 ) ;
147
153
let e_limb = compose :: < AB :: Expr > ( & e[ j * 16 ..( j + 1 ) * 16 ] , 1 ) ;
148
154
149
- // If it is a padding row or the last row of a message, the `hash` should be the [SHA256_H ]
155
+ // If it is a padding row or the last row of a message, the `hash` should be the [SHA_H ]
150
156
builder
151
157
. when (
152
158
next. flags . is_padding_row ( )
@@ -278,24 +284,24 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
278
284
// Constrain how much the row index changes by
279
285
// round->round: 1
280
286
// round->digest: 1
281
- // digest->round: -16 // TODO: sha512
287
+ // digest->round: -C::ROUND_ROWS
282
288
// digest->padding: 1
283
289
// padding->padding: 0
284
290
// Other transitions are not allowed by the above constraints
285
291
let delta = * local_cols. flags . is_round_row * AB :: Expr :: ONE
286
292
+ * local_cols. flags . is_digest_row
287
293
* * next_cols. flags . is_round_row
288
- * AB :: Expr :: from_canonical_u32 ( 16 )
294
+ * AB :: Expr :: from_canonical_usize ( C :: ROUND_ROWS )
289
295
* AB :: Expr :: NEG_ONE
290
296
+ * local_cols. flags . is_digest_row * next_is_padding_row. clone ( ) * AB :: Expr :: ONE ;
291
297
292
298
let local_row_idx = self . row_idx_encoder . flag_with_val :: < AB > (
293
299
local_cols. flags . row_idx . to_slice ( ) . unwrap ( ) ,
294
- & ( 0 ..18 ) . map ( |i| ( i, i) ) . collect :: < Vec < _ > > ( ) ,
300
+ & ( 0 ..= C :: ROWS_PER_BLOCK ) . map ( |i| ( i, i) ) . collect :: < Vec < _ > > ( ) ,
295
301
) ;
296
302
let next_row_idx = self . row_idx_encoder . flag_with_val :: < AB > (
297
303
next_cols. flags . row_idx . to_slice ( ) . unwrap ( ) ,
298
- & ( 0 ..18 ) . map ( |i| ( i, i) ) . collect :: < Vec < _ > > ( ) ,
304
+ & ( 0 ..= C :: ROWS_PER_BLOCK ) . map ( |i| ( i, i) ) . collect :: < Vec < _ > > ( ) ,
299
305
) ;
300
306
301
307
builder
@@ -458,20 +464,22 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
458
464
}
459
465
460
466
// Constrain intermed for `next` row
461
- // We will only constrain intermed_12 for rows [3, 14], and let it be unconstrained for other rows
467
+ // We will only constrain intermed_12 for rows [3, 14], and let it unconstrained for other rows
462
468
// Other rows should put the needed value in intermed_12 to make the below summation constraint hold
463
- let is_row_3_14 = self
464
- . row_idx_encoder
465
- . contains_flag_range :: < AB > ( next. flags . row_idx . to_slice ( ) . unwrap ( ) , 3 ..=14 ) ;
466
- // We will only constrain intermed_8 for rows [2, 13], and let it unconstrained for other rows
467
- let is_row_2_13 = self
468
- . row_idx_encoder
469
- . contains_flag_range :: < AB > ( next. flags . row_idx . to_slice ( ) . unwrap ( ) , 2 ..=13 ) ;
469
+ let is_row_intermed_12 = self . row_idx_encoder . contains_flag_range :: < AB > (
470
+ next. flags . row_idx . to_slice ( ) . unwrap ( ) ,
471
+ 3 ..=C :: ROUND_ROWS - 2 ,
472
+ ) ;
473
+ // We will only constrain intermed_8 for rows [2, C::ROUND_ROWS - 2], and let it unconstrained for other rows
474
+ let is_row_intermed_8 = self . row_idx_encoder . contains_flag_range :: < AB > (
475
+ next. flags . row_idx . to_slice ( ) . unwrap ( ) ,
476
+ 2 ..=C :: ROUND_ROWS - 3 ,
477
+ ) ;
470
478
for i in 0 ..C :: ROUNDS_PER_ROW {
471
479
// w_idx
472
480
let w_idx = w. row ( i) . mapv ( |x| x. into ( ) ) . to_vec ( ) ;
473
481
// sig_0(w_{idx+1})
474
- let sig_w = small_sig0_field :: < AB :: Expr > ( w. row ( i + 1 ) . as_slice ( ) . unwrap ( ) ) ;
482
+ let sig_w = small_sig0_field :: < AB :: Expr , C > ( w. row ( i + 1 ) . as_slice ( ) . unwrap ( ) ) ;
475
483
for j in 0 ..C :: WORD_U16S {
476
484
let w_idx_limb = compose :: < AB :: Expr > ( & w_idx[ j * 16 ..( j + 1 ) * 16 ] , 1 ) ;
477
485
let sig_w_limb = compose :: < AB :: Expr > ( & sig_w[ j * 16 ..( j + 1 ) * 16 ] , 1 ) ;
@@ -483,12 +491,12 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
483
491
w_idx_limb + sig_w_limb,
484
492
) ;
485
493
486
- builder. when ( is_row_2_13 . clone ( ) ) . assert_eq (
494
+ builder. when ( is_row_intermed_8 . clone ( ) ) . assert_eq (
487
495
next. schedule_helper . intermed_8 [ [ i, j] ] ,
488
496
local. schedule_helper . intermed_4 [ [ i, j] ] ,
489
497
) ;
490
498
491
- builder. when ( is_row_3_14 . clone ( ) ) . assert_eq (
499
+ builder. when ( is_row_intermed_12 . clone ( ) ) . assert_eq (
492
500
next. schedule_helper . intermed_12 [ [ i, j] ] ,
493
501
local. schedule_helper . intermed_8 [ [ i, j] ] ,
494
502
) ;
@@ -524,7 +532,7 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
524
532
constraint_word_addition :: < _ , C > (
525
533
// Note: here we can't do a conditional check because the degree of sum is already 3
526
534
& mut builder. when_transition ( ) ,
527
- & [ & small_sig1_field :: < AB :: Expr > (
535
+ & [ & small_sig1_field :: < AB :: Expr , C > (
528
536
w. row ( i + 2 ) . as_slice ( ) . unwrap ( ) ,
529
537
) ] ,
530
538
& [ & w_7, intermed_16. as_slice ( ) . unwrap ( ) ] ,
@@ -533,13 +541,13 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
533
541
) ;
534
542
535
543
for j in 0 ..C :: WORD_U16S {
536
- // When on rows 4..16 message schedule carries should be 0 or 1
537
- let is_row_4_15 = * next. flags . is_round_row - * next. flags . is_first_4_rows ;
544
+ // When on rows 4..C::ROUND_ROWS message schedule carries should be 0 or 1
545
+ let is_row_4_or_more = * next. flags . is_round_row - * next. flags . is_first_4_rows ;
538
546
builder
539
- . when ( is_row_4_15 . clone ( ) )
547
+ . when ( is_row_4_or_more . clone ( ) )
540
548
. assert_bool ( next. message_schedule . carry_or_buffer [ [ i, j * 2 ] ] ) ;
541
549
builder
542
- . when ( is_row_4_15 )
550
+ . when ( is_row_4_or_more )
543
551
. assert_bool ( next. message_schedule . carry_or_buffer [ [ i, j * 2 + 1 ] ] ) ;
544
552
}
545
553
// Constrain w being composed of bits
@@ -551,7 +559,7 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
551
559
}
552
560
}
553
561
554
- /// Constrain the work vars on `next` row according to the sha256 documentation
562
+ /// Constrain the work vars on `next` row according to the sha documentation
555
563
/// Refer to [https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf]
556
564
fn eval_work_vars < ' a , AB : InteractionBuilder > (
557
565
& self ,
@@ -588,11 +596,12 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
588
596
) * * next. flags . is_round_row
589
597
} )
590
598
. collect :: < Vec < _ > > ( ) ;
599
+
591
600
let k_limbs = ( 0 ..C :: WORD_U16S )
592
601
. map ( |j| {
593
602
self . row_idx_encoder . flag_with_val :: < AB > (
594
603
next. flags . row_idx . to_slice ( ) . unwrap ( ) ,
595
- & ( 0 ..16 )
604
+ & ( 0 ..C :: ROUND_ROWS )
596
605
. map ( |rw_idx| {
597
606
(
598
607
rw_idx,
@@ -613,13 +622,13 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
613
622
builder,
614
623
& [
615
624
e. row ( i) . mapv ( |x| x. into ( ) ) . as_slice ( ) . unwrap ( ) , // previous `h`
616
- & big_sig1_field :: < AB :: Expr > ( e. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ) , // sig_1 of previous `e`
625
+ & big_sig1_field :: < AB :: Expr , C > ( e. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ) , // sig_1 of previous `e`
617
626
& ch_field :: < AB :: Expr > (
618
627
e. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ,
619
628
e. row ( i + 2 ) . as_slice ( ) . unwrap ( ) ,
620
629
e. row ( i + 1 ) . as_slice ( ) . unwrap ( ) ,
621
630
) , // Ch of previous `e`, `f`, `g`
622
- & big_sig0_field :: < AB :: Expr > ( a. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ) , // sig_0 of previous `a`
631
+ & big_sig0_field :: < AB :: Expr , C > ( a. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ) , // sig_0 of previous `a`
623
632
& maj_field :: < AB :: Expr > (
624
633
a. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ,
625
634
a. row ( i + 2 ) . as_slice ( ) . unwrap ( ) ,
@@ -637,9 +646,9 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ShaAir<C> {
637
646
constraint_word_addition :: < _ , C > (
638
647
builder,
639
648
& [
640
- & a. row ( i) . mapv ( |x| x. into ( ) ) . as_slice ( ) . unwrap ( ) , // previous `d`
641
- & e. row ( i) . mapv ( |x| x. into ( ) ) . as_slice ( ) . unwrap ( ) , // previous `h`
642
- & big_sig1_field :: < AB :: Expr > ( e. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ) , // sig_1 of previous `e`
649
+ a. row ( i) . mapv ( |x| x. into ( ) ) . as_slice ( ) . unwrap ( ) , // previous `d`
650
+ e. row ( i) . mapv ( |x| x. into ( ) ) . as_slice ( ) . unwrap ( ) , // previous `h`
651
+ & big_sig1_field :: < AB :: Expr , C > ( e. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ) , // sig_1 of previous `e`
643
652
& ch_field :: < AB :: Expr > (
644
653
e. row ( i + 3 ) . as_slice ( ) . unwrap ( ) ,
645
654
e. row ( i + 2 ) . as_slice ( ) . unwrap ( ) ,
0 commit comments