Skip to content

Commit dee38a0

Browse files
WIP: update vm chip to support sha512
1 parent 816edcc commit dee38a0

File tree

13 files changed

+376
-283
lines changed

13 files changed

+376
-283
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ rrs-lib = "0.1.0"
212212
rand = { version = "0.8.5", default-features = false }
213213
hex = { version = "0.4.3", default-features = false }
214214
serde-big-array = "0.5.1"
215+
ndarray = "0.16"
215216

216217
# default-features = false for no_std for use in guest programs
217218
itertools = { version = "0.14.0", default-features = false }

crates/circuits/sha-air/src/config.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,14 @@ pub trait ShaConfig: Send + Sync + Clone {
7777
} else {
7878
Self::DIGEST_WIDTH
7979
};
80-
}
8180

82-
/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows
83-
/// To optimize the trace generation of invalid rows, we precompute those values.
84-
/// This trait also stores the constants K and H for the given SHA config.
85-
pub trait ShaPrecomputedValues<T> {
81+
/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows
82+
/// To optimize the trace generation of invalid rows, we precompute those values.
8683
// these should be appropriately sized for the config
8784
fn get_invalid_carry_a(round_num: usize) -> &'static [u32];
8885
fn get_invalid_carry_e(round_num: usize) -> &'static [u32];
86+
87+
/// We also store the SHA constants K and H
8988
fn get_k() -> &'static [Self::Word];
9089
fn get_h() -> &'static [Self::Word];
9190
}

crates/circuits/sha-air/src/tests.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use crate::{ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut};
12
use std::{borrow::BorrowMut, cmp::max, sync::Arc};
2-
use crate::{ShaDigestColsRefMut, ShaRoundColsRefMut, ShaRoundColsRef};
33

44
use openvm_circuit::arch::{
55
instructions::riscv::RV32_CELL_BITS,
@@ -22,9 +22,7 @@ use openvm_stark_backend::{
2222
use openvm_stark_sdk::utils::create_seeded_rng;
2323
use rand::Rng;
2424

25-
use crate::{
26-
compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig,
27-
};
25+
use crate::{compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig};
2826

2927
// A wrapper AIR purely for testing purposes
3028
#[derive(Clone, Debug)]
@@ -125,14 +123,13 @@ fn rand_sha512_test() {
125123

126124
// A wrapper Chip to test that the final_hash is properly constrained.
127125
// This chip implements a malicious trace gen that violates the final_hash constraints.
128-
pub struct ShaTestBadFinalHashChip<C: ShaConfig + ShaPrecomputedValues<C::Word>> {
126+
pub struct ShaTestBadFinalHashChip<C: ShaConfig> {
129127
pub air: ShaTestAir<C>,
130128
pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>,
131129
pub records: Vec<(Vec<u8>, bool)>, // length of inner vec should be C::BLOCK_U8S
132130
}
133131

134-
impl<SC: StarkGenericConfig, C: ShaConfig + ShaPrecomputedValues<C::Word> + 'static> Chip<SC>
135-
for ShaTestBadFinalHashChip<C>
132+
impl<SC: StarkGenericConfig, C: ShaConfig + 'static> Chip<SC> for ShaTestBadFinalHashChip<C>
136133
where
137134
Val<SC>: PrimeField32,
138135
{
@@ -170,7 +167,10 @@ where
170167
let mut last_digest_row: crate::ShaRoundColsRefMut<Val<SC>> =
171168
ShaRoundColsRefMut::from::<C>(last_digest_row.borrow_mut());
172169
// fix the intermed_4 for the digest row
173-
generate_intermed_4::<Val<SC>, C>(&ShaRoundColsRef::from_mut::<C>(&last_round_row), &mut last_digest_row);
170+
generate_intermed_4::<Val<SC>, C>(
171+
&ShaRoundColsRef::from_mut::<C>(&last_round_row),
172+
&mut last_digest_row,
173+
);
174174
}
175175
}
176176

@@ -190,7 +190,7 @@ where
190190

191191
// Copy of private method in Sha256Air used for testing
192192
/// Puts the correct intermed_4 in the `next_row`
193-
fn generate_intermed_4<F: PrimeField32, C: ShaConfig + ShaPrecomputedValues<C::Word>>(
193+
fn generate_intermed_4<F: PrimeField32, C: ShaConfig>(
194194
local_cols: &ShaRoundColsRef<F>,
195195
next_cols: &mut ShaRoundColsRefMut<F>,
196196
) {
@@ -209,10 +209,9 @@ fn generate_intermed_4<F: PrimeField32, C: ShaConfig + ShaPrecomputedValues<C::W
209209
.collect::<Vec<_>>(),
210210
]
211211
.concat();
212-
213-
212+
214213
// length of inner vec is C::WORD_U16S
215-
let w_limbs: Vec<Vec<F>> = w
214+
let w_limbs: Vec<Vec<F>> = w
216215
.iter()
217216
.map(|x| {
218217
(0..C::WORD_U16S)
@@ -231,7 +230,7 @@ fn generate_intermed_4<F: PrimeField32, C: ShaConfig + ShaPrecomputedValues<C::W
231230
}
232231
}
233232

234-
impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ChipUsageGetter for ShaTestBadFinalHashChip<C> {
233+
impl<C: ShaConfig> ChipUsageGetter for ShaTestBadFinalHashChip<C> {
235234
fn air_name(&self) -> String {
236235
get_air_name(&self.air)
237236
}
@@ -244,14 +243,21 @@ impl<C: ShaConfig + ShaPrecomputedValues<C::Word>> ChipUsageGetter for ShaTestBa
244243
}
245244
}
246245

247-
fn test_sha_final_hash_constraints<C: ShaConfig + ShaPrecomputedValues<C::Word> + 'static>() {
246+
fn test_sha_final_hash_constraints<C: ShaConfig + 'static>() {
248247
let mut rng = create_seeded_rng();
249248
let tester = VmChipTestBuilder::default();
250249
let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS);
251250
let bitwise_chip = SharedBitwiseOperationLookupChip::<RV32_CELL_BITS>::new(bitwise_bus);
252251
let len = rng.gen_range(1..100);
253252
let random_records: Vec<_> = (0..len)
254-
.map(|_| ((0..C::BLOCK_U8S).map(|_| rng.gen::<u8>()).collect::<Vec<_>>(), true))
253+
.map(|_| {
254+
(
255+
(0..C::BLOCK_U8S)
256+
.map(|_| rng.gen::<u8>())
257+
.collect::<Vec<_>>(),
258+
true,
259+
)
260+
})
255261
.collect();
256262
let chip = ShaTestBadFinalHashChip {
257263
air: ShaTestAir {

crates/circuits/sha-macros/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ fn get_const_cols_ref_fields(
292292
let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap());
293293

294294
if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) {
295-
// treat the field as a struct that derives AlignedBorrow
295+
// treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config)
296296
let f_ty = &f.ty;
297297
return Ok(FieldInfo {
298298
ty: parse_quote! {

extensions/sha256/circuit/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ openvm-instructions = { workspace = true }
1616
openvm-sha256-transpiler = { workspace = true }
1717
openvm-rv32im-circuit = { workspace = true }
1818
openvm-sha-air = { workspace = true }
19+
openvm-sha-macros = { workspace = true }
1920

2021
derive-new.workspace = true
2122
derive_more = { workspace = true, features = ["from"] }
2223
rand.workspace = true
2324
serde.workspace = true
2425
sha2 = { version = "0.10", default-features = false }
2526
strum = { workspace = true }
27+
ndarray.workspace = true
2628

2729
[dev-dependencies]
2830
openvm-stark-sdk = { workspace = true }

extensions/sha256/circuit/src/extension.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ use openvm_rv32im_circuit::{
1717
Rv32MExecutor, Rv32MPeriphery,
1818
};
1919
use openvm_sha256_transpiler::Rv32Sha256Opcode;
20+
use openvm_sha_air::Sha256Config;
2021
use openvm_stark_backend::p3_field::PrimeField32;
2122
use serde::{Deserialize, Serialize};
2223
use strum::IntoEnumIterator;
2324

2425
use crate::*;
2526

2627
#[derive(Clone, Debug, VmConfig, derive_new::new, Serialize, Deserialize)]
27-
pub struct Sha256Rv32Config {
28+
pub struct Sha2Rv32Config {
2829
#[system]
2930
pub system: SystemConfig,
3031
#[extension]
@@ -34,38 +35,39 @@ pub struct Sha256Rv32Config {
3435
#[extension]
3536
pub io: Rv32Io,
3637
#[extension]
37-
pub sha256: Sha256,
38+
pub sha2: Sha2,
3839
}
3940

40-
impl Default for Sha256Rv32Config {
41+
impl Default for Sha2Rv32Config {
4142
fn default() -> Self {
4243
Self {
4344
system: SystemConfig::default().with_continuations(),
4445
rv32i: Rv32I,
4546
rv32m: Rv32M::default(),
4647
io: Rv32Io,
47-
sha256: Sha256,
48+
sha2: Sha2,
4849
}
4950
}
5051
}
5152

5253
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
53-
pub struct Sha256;
54+
pub struct Sha2;
5455

5556
#[derive(ChipUsageGetter, Chip, InstructionExecutor, From, AnyEnum)]
56-
pub enum Sha256Executor<F: PrimeField32> {
57-
Sha256(Sha256VmChip<F>),
57+
pub enum Sha2Executor<F: PrimeField32> {
58+
Sha256(ShaVmChip<F, Sha256Config>),
59+
Sha512(ShaVmChip<F, Sha512Config>),
5860
}
5961

6062
#[derive(From, ChipUsageGetter, Chip, AnyEnum)]
61-
pub enum Sha256Periphery<F: PrimeField32> {
63+
pub enum ShaPeriphery<F: PrimeField32> {
6264
BitwiseOperationLookup(SharedBitwiseOperationLookupChip<8>),
6365
Phantom(PhantomChip<F>),
6466
}
6567

66-
impl<F: PrimeField32> VmExtension<F> for Sha256 {
67-
type Executor = Sha256Executor<F>;
68-
type Periphery = Sha256Periphery<F>;
68+
impl<F: PrimeField32> VmExtension<F> for Sha2 {
69+
type Executor = ShaExecutor<F>;
70+
type Periphery = ShaPeriphery<F>;
6971

7072
fn build(
7173
&self,
@@ -84,7 +86,7 @@ impl<F: PrimeField32> VmExtension<F> for Sha256 {
8486
chip
8587
};
8688

87-
let sha256_chip = Sha256VmChip::new(
89+
let sha256_chip = ShaVmChip::new(
8890
builder.system_port(),
8991
builder.system_config().memory_config.pointer_max_bits,
9092
bitwise_lu_chip,

0 commit comments

Comments
 (0)