From 33bf3e67342fa76ebc3fabbdfe33f2dfc0327a24 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Thu, 6 Feb 2025 13:35:18 -0500 Subject: [PATCH 1/7] Added sha-macros. Derive ColsRef to generate a ColsRef struct --- Cargo.lock | 62 ++- Cargo.toml | 1 + crates/circuits/sha-macros/Cargo.toml | 21 + crates/circuits/sha-macros/src/lib.rs | 476 ++++++++++++++++++ crates/circuits/sha-macros/tests/flags.rs | 35 ++ crates/circuits/sha-macros/tests/nested.rs | 38 ++ crates/circuits/sha-macros/tests/simple.rs | 17 + crates/circuits/sha-macros/tests/work-vars.rs | 28 ++ crates/circuits/sha256-air/src/config.rs | 321 ++++++++++++ 9 files changed, 995 insertions(+), 4 deletions(-) create mode 100644 crates/circuits/sha-macros/Cargo.toml create mode 100644 crates/circuits/sha-macros/src/lib.rs create mode 100644 crates/circuits/sha-macros/tests/flags.rs create mode 100644 crates/circuits/sha-macros/tests/nested.rs create mode 100644 crates/circuits/sha-macros/tests/simple.rs create mode 100644 crates/circuits/sha-macros/tests/work-vars.rs create mode 100644 crates/circuits/sha256-air/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 836ac14fec..19b446e756 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2725,6 +2725,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -2899,6 +2908,16 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "maybe-rayon" version = "0.1.1" @@ -3016,12 +3035,18 @@ dependencies = [ ] [[package]] -name = "nibble_vec" -version = "0.1.0" +name = "ndarray" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" dependencies = [ - "smallvec", + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", ] [[package]] @@ -4079,12 +4104,26 @@ dependencies = [ "tracing", ] +[[package]] +name = "openvm-sha-macros" +version = "1.0.0-rc.0" +dependencies = [ + "itertools 0.14.0", + "ndarray", + "openvm-macros-common", + "openvm-sha256-air", + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "openvm-sha256-air" version = "1.0.0-rc.2" dependencies = [ "openvm-circuit", "openvm-circuit-primitives", + "openvm-sha-macros", "openvm-stark-backend", "openvm-stark-sdk", "rand", @@ -4790,6 +4829,15 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "poseidon-primitives" version = "0.2.0" @@ -4995,6 +5043,12 @@ dependencies = [ "bitflags", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.10.0" diff --git a/Cargo.toml b/Cargo.toml index 03c1c2eb06..f384bb3615 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,6 +113,7 @@ openvm-sdk = { path = "crates/sdk", default-features = false } openvm-mod-circuit-builder = { path = "crates/circuits/mod-builder", default-features = false } openvm-poseidon2-air = { path = "crates/circuits/poseidon2-air", default-features = false } openvm-sha256-air = { path = "crates/circuits/sha256-air", default-features = false } +openvm-sha-macros = { path = "crates/circuits/sha-macros", default-features = false } openvm-circuit-primitives = { path = "crates/circuits/primitives", default-features = false } openvm-circuit-primitives-derive = { path = "crates/circuits/primitives/derive", default-features = false } openvm = { path = "crates/toolchain/openvm", default-features = false } diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml new file mode 100644 index 0000000000..7ed1af42d2 --- /dev/null +++ b/crates/circuits/sha-macros/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "openvm-sha-macros" +version.workspace = true +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +syn = { version = "2.0", features = ["full", "extra-traits"] } +quote = "1.0" +openvm-macros-common = { workspace = true, default-features = false } +itertools = "0.14" +proc-macro2 = "1.0" + +[dev-dependencies] +openvm-sha256-air = { workspace = true } +ndarray = "0.16" + +[lib] +proc-macro = true diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs new file mode 100644 index 0000000000..19505448df --- /dev/null +++ b/crates/circuits/sha-macros/src/lib.rs @@ -0,0 +1,476 @@ +#![feature(proc_macro_diagnostic)] + +extern crate proc_macro; + +use itertools::Itertools; +//use openvm_macros_common::MacroArgs; +use proc_macro::TokenStream; +use quote::{format_ident, quote}; +use syn::{parse_macro_input, parse_quote, DeriveInput, Expr}; + +#[proc_macro_derive(ColsRef, attributes(dim))] +pub fn cols_ref(input: TokenStream) -> TokenStream { + let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput); + + let span = derive_input.ident.span().clone(); + let res = cols_ref_impl(derive_input); + if res.is_err() { + return syn::Error::new(span, res.err().unwrap().to_string()) + .to_compile_error() + .into(); + } else { + res.unwrap().into() + } +} + +fn cols_ref_impl(derive_input: DeriveInput) -> Result { + let DeriveInput { + ident, + generics, + data, + vis, + .. + } = derive_input; + + let generic_types = generics + .params + .iter() + .filter_map(|p| { + if let syn::GenericParam::Type(type_param) = p { + Some(type_param) + } else { + None + } + }) + .collect::>(); + + if generic_types.len() != 1 { + return Err("Struct must have exactly one generic type parameter".to_string()); + } + + let generic_type = generic_types[0]; + + match data { + syn::Data::Struct(data_struct) => { + let const_field_infos: Vec = data_struct + .fields + .iter() + .map(|f| get_const_cols_ref_fields(f, generic_type)) + .collect::, String>>() + .map_err(|e| format!("Failed to process fields. {}", e))?; + + let const_cols_ref_name = syn::Ident::new(&format!("{}Ref", ident), ident.span()); + let from_args = quote! { slice: &'a [#generic_type] }; + + let struct_info = StructInfo { + name: const_cols_ref_name, + vis: vis.clone(), + generic_type: generic_type.clone(), + field_infos: const_field_infos, + fields: data_struct.fields.clone(), + from_args, + derive_clone: true, + }; + + let const_cols_ref_struct = make_struct(struct_info.clone()); + + let from_mut_impl = make_from_mut(struct_info)?; + + let mut_field_infos: Vec = data_struct + .fields + .iter() + .map(|f| get_mut_cols_ref_fields(f, generic_type)) + .collect::, String>>() + .map_err(|e| format!("Failed to process fields. {}", e))?; + + let mut_cols_ref_name = syn::Ident::new(&format!("{}RefMut", ident), ident.span()); + let from_args = quote! { slice: &'a mut [#generic_type] }; + + let struct_info = StructInfo { + name: mut_cols_ref_name, + vis, + generic_type: generic_type.clone(), + field_infos: mut_field_infos, + fields: data_struct.fields, + from_args, + derive_clone: false, + }; + + let mut_cols_ref_struct = make_struct(struct_info); + + Ok(quote! { + #const_cols_ref_struct + #from_mut_impl + #mut_cols_ref_struct + }) + } + _ => Err("ColsRef can only be derived for structs".to_string()), + } +} + +#[derive(Debug, Clone)] +struct StructInfo { + name: syn::Ident, + vis: syn::Visibility, + generic_type: syn::TypeParam, + field_infos: Vec, + fields: syn::Fields, + from_args: proc_macro2::TokenStream, + derive_clone: bool, +} + +fn make_struct(struct_info: StructInfo) -> proc_macro2::TokenStream { + let StructInfo { + name, + vis, + generic_type, + field_infos, + fields, + from_args, + derive_clone, + } = struct_info; + + let field_types = field_infos.iter().map(|f| &f.ty).collect_vec(); + let length_exprs = field_infos.iter().map(|f| &f.length_expr).collect_vec(); + let prepare_subslices = field_infos + .iter() + .map(|f| &f.prepare_subslice) + .collect_vec(); + let initializers = field_infos.iter().map(|f| &f.initializer).collect_vec(); + + let idents = fields.iter().map(|f| &f.ident).collect_vec(); + + let clone_impl = if derive_clone { + quote! { + #[derive(Clone)] + } + } else { + quote! {} + }; + + quote! { + #clone_impl + #vis struct #name <'a, #generic_type> { + #( pub #idents: #field_types ),* + } + + impl<'a, #generic_type> #name<'a, #generic_type> { + pub fn from(#from_args) -> Self { + #( #prepare_subslices )* + Self { + #( #idents: #initializers ),* + } + } + + pub fn len() -> usize { + 0 #( + #length_exprs )* + } + } + } +} + +fn make_from_mut(struct_info: StructInfo) -> Result { + let StructInfo { + name, + vis, + generic_type, + field_infos, + fields, + from_args, + derive_clone, + } = struct_info; + + let fields = match fields { + syn::Fields::Named(fields) => fields.named, + _ => { + return Err("Fields must be named".to_string()); + } + }; + + let from_mut_impl = fields + .iter() + .map(|f| { + let ident = f.ident.clone().unwrap(); + match &f.ty { + syn::Type::Path(type_path) => { + let first_ident = type_path.path.segments.first().unwrap().ident.to_string(); + if first_ident.ends_with("Cols") { + // lifetime 'b is used in from_mut to allow more flexible lifetime of return value + let cols_ref_type = + get_const_cols_ref_type(&f.ty, &generic_type, parse_quote! { 'b }); + Ok(quote! { + <#cols_ref_type>::from_mut::(&other.#ident) + }) + } else { + // Not a ColsRef type, so the type is T + Ok(quote! { + &other.#ident + }) + } + } + syn::Type::Array(_) => { + // type is nested array of T + Ok(quote! { + other.#ident.view() + }) + } + _ => Err(format!("Unsupported type: {:?}", f.ty)), + } + }) + .collect::, String>>()?; + + let field_idents = fields + .iter() + .map(|f| f.ident.clone().unwrap()) + .collect_vec(); + + let mut_struct_ident = format_ident!("{}Mut", name.to_string()); + let mut_struct_type: syn::Type = parse_quote! { + #mut_struct_ident<'a, #generic_type> + }; + + Ok(parse_quote! { + impl<'b, #generic_type> #name<'b, #generic_type> { + pub fn from_mut<'a, C: ShaConfig>(other: &'b #mut_struct_type) -> Self + { + Self { + #( #field_idents: #from_mut_impl ),* + } + } + } + }) +} + +#[derive(Debug, Clone)] +struct FieldInfo { + // type for struct definition + ty: syn::Type, + // an expr calculating the length of the field + length_expr: proc_macro2::TokenStream, + // prepare a subslice of the slice to be used in the 'from' method + prepare_subslice: proc_macro2::TokenStream, + // an expr used in the Self initializer in the 'from' method + // may refer to the subslice declared in prepare_subslice + initializer: proc_macro2::TokenStream, +} + +// Prepare the fields for the const ColsRef struct +fn get_const_cols_ref_fields( + f: &syn::Field, + generic_type: &syn::TypeParam, +) -> Result { + let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); + let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); + match get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }) { + Some(const_cols_ref_type) => Ok(FieldInfo { + ty: parse_quote! { + #const_cols_ref_type + }, + length_expr: quote! { + <#const_cols_ref_type>::len::() + }, + prepare_subslice: quote! { + let #length_var = <#const_cols_ref_type>::len::(); + let (#slice_var, slice) = slice.split_at(#length_var); + let #slice_var = <#const_cols_ref_type>::from::(#slice_var); + }, + initializer: quote! { + #slice_var + }, + }), + None => { + // Not a ColsRef type, so assume it is T (the generic type) or a nested array of T + let dims = get_dims(&f.ty).map_err(|e| { + format!( + "Failed to parse the type of the field '{}'. {}", + f.ident.clone().unwrap(), + e + ) + })?; + + if dims.is_empty() { + // the field has type T + Ok(FieldInfo { + ty: parse_quote! { + &'a #generic_type + }, + length_expr: quote! { + 1 + }, + prepare_subslice: quote! { + let #length_var = 1; + let (#slice_var, slice) = slice.split_at(#length_var); + }, + initializer: quote! { + &#slice_var[0] + }, + }) + } else { + // nested array of T + let ndarray_ident: syn::Ident = format_ident!("ArrayView{}", dims.len()); + let ndarray_type: syn::Type = parse_quote! { + ndarray::#ndarray_ident<'a, #generic_type> + }; + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: quote! { + 1 #(* C::#dims)* + }, + prepare_subslice: quote! { + let #length_var = 1 #(* C::#dims)*; + let (#slice_var, slice) = slice.split_at(#length_var); + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(C::#dims),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } + } + } +} + +// Prepare the fields for the mut ColsRef struct +fn get_mut_cols_ref_fields( + f: &syn::Field, + generic_type: &syn::TypeParam, +) -> Result { + let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); + let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); + match get_mut_cols_ref_type(&f.ty, generic_type) { + Some(mut_cols_ref_type) => Ok(FieldInfo { + ty: parse_quote! { + #mut_cols_ref_type + }, + length_expr: quote! { + <#mut_cols_ref_type>::len::() + }, + prepare_subslice: quote! { + let #length_var = <#mut_cols_ref_type>::len::(); + let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); + let #slice_var = <#mut_cols_ref_type>::from::(#slice_var); + }, + initializer: quote! { + #slice_var + }, + }), + None => { + // Not a ColsRef type, so assume it is T (the generic type) or a nested array of T + let dims = get_dims(&f.ty).map_err(|e| { + format!( + "Failed to parse the type of the field '{}'. {}", + f.ident.clone().unwrap(), + e + ) + })?; + + if dims.is_empty() { + // the field has type T + Ok(FieldInfo { + ty: parse_quote! { + &'a mut #generic_type + }, + length_expr: quote! { + 1 + }, + prepare_subslice: quote! { + let #length_var = 1; + let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); + }, + initializer: quote! { + &mut #slice_var[0] + }, + }) + } else { + // nested array of T + let ndarray_ident: syn::Ident = format_ident!("ArrayViewMut{}", dims.len()); + let ndarray_type: syn::Type = parse_quote! { + ndarray::#ndarray_ident<'a, #generic_type> + }; + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: quote! { + 1 #(* C::#dims)* + }, + prepare_subslice: quote! { + let #length_var = 1 #(* C::#dims)*; + let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); + let mut #slice_var = ndarray::#ndarray_ident::from_shape( ( #(C::#dims),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } + } + } +} + +// If 'ty' is a struct that derives ColsRef, return the ColsRef struct type +// Otherwise, return None +fn get_const_cols_ref_type( + ty: &syn::Type, + generic_type: &syn::TypeParam, + lifetime: syn::Lifetime, +) -> Option { + if let syn::Type::Path(type_path) = ty { + type_path.path.segments.iter().last().and_then(|s| { + if s.ident.to_string().ends_with("Cols") { + let const_cols_ref_ident = format_ident!("{}Ref", s.ident); + let const_cols_ref_type = parse_quote! { + #const_cols_ref_ident<#lifetime, #generic_type> + }; + Some(const_cols_ref_type) + } else { + None + } + }) + } else { + None + } +} + +// If 'ty' is a struct that derives ColsRef, return the ColsRefMut struct type +// Otherwise, return None +fn get_mut_cols_ref_type(ty: &syn::Type, generic_type: &syn::TypeParam) -> Option { + if let syn::Type::Path(type_path) = ty { + type_path.path.segments.iter().last().and_then(|s| { + if s.ident.to_string().ends_with("Cols") { + let mut_cols_ref_ident = format_ident!("{}RefMut", s.ident); + let mut_cols_ref_type = parse_quote! { + #mut_cols_ref_ident<'a, #generic_type> + }; + Some(mut_cols_ref_type) + } else { + None + } + }) + } else { + None + } +} + +fn get_dims(ty: &syn::Type) -> Result, String> { + get_dims_impl(ty).map(|dims| dims.into_iter().rev().collect()) +} + +fn get_dims_impl(ty: &syn::Type) -> Result, String> { + match ty { + syn::Type::Array(array) => { + let mut dims = get_dims(array.elem.as_ref())?; + match array.len { + syn::Expr::Path(_) => dims.push(array.len.clone()), + _ => return Err("Array lengths must be const generic parameters.".to_string()), + } + Ok(dims) + } + syn::Type::Path(_) => Ok(Vec::new()), + _ => Err( + "Only generic types and (nested) arrays of generic types are supported.".to_string(), + ), + } +} diff --git a/crates/circuits/sha-macros/tests/flags.rs b/crates/circuits/sha-macros/tests/flags.rs new file mode 100644 index 0000000000..cfd048f027 --- /dev/null +++ b/crates/circuits/sha-macros/tests/flags.rs @@ -0,0 +1,35 @@ +use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_macros::ColsRef; + +#[repr(C)] +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaFlagsCols { + pub is_round_row: T, + /// A flag that indicates if the current row is among the first 4 rows of a block + pub is_first_4_rows: T, + pub is_digest_row: T, + pub is_last_block: T, + /// We will encode the row index [0..17) using 5 cells + //#[length(ROW_VAR_CNT)] + pub row_idx: [T; ROW_VAR_CNT], + /// The global index of the current block + pub global_block_idx: T, + /// Will store the index of the current block in the current message starting from 0 + pub local_block_idx: T, +} + +#[test] +fn flags() { + let input = [1; 4 + 5 + 2]; + let test: ShaFlagsColsRef = ShaFlagsColsRef::from::(&input); + println!( + "{}\n{}\n{}\n{}\n{:?}\n{}\n{}", + test.is_round_row, + test.is_first_4_rows, + test.is_digest_row, + test.is_last_block, + test.row_idx, + test.global_block_idx, + test.local_block_idx + ); +} diff --git a/crates/circuits/sha-macros/tests/nested.rs b/crates/circuits/sha-macros/tests/nested.rs new file mode 100644 index 0000000000..82bf757964 --- /dev/null +++ b/crates/circuits/sha-macros/tests/nested.rs @@ -0,0 +1,38 @@ +use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_macros::ColsRef; + +#[derive(ColsRef)] +struct Test1Cols { + pub a: T, + pub nested: Test2Cols, +} + +#[derive(ColsRef)] +struct Test2Cols { + pub b: T, + pub c: [T; WORD_BITS], +} + +#[test] +fn nested_const() { + let input = [0; 1 + 1 + 32]; + let test: Test1ColsRef = Test1ColsRef::from::(&input); + println!("{}, {}, {}", test.a, test.nested.b, test.nested.c); +} + +#[test] +fn nested_mut() { + let mut input = [0; 1 + 1 + 32]; + let mut test: Test1ColsRefMut = Test1ColsRefMut::from::(&mut input); + *test.nested.b = 1u32; + test.nested.c[0] = 1u32; + println!("{}, {}, {}", test.a, test.nested.b, test.nested.c); +} + +#[test] +fn nested_from_mut() { + let mut mut_input = [0; 1 + 1 + 32]; + let mut mut_test: Test1ColsRefMut = Test1ColsRefMut::from::(&mut mut_input); + let const_test: Test1ColsRef = Test1ColsRef::from_mut::(&mut mut_test); + println!("{}, {}, {}", const_test.a, const_test.nested.b, const_test.nested.c); +} diff --git a/crates/circuits/sha-macros/tests/simple.rs b/crates/circuits/sha-macros/tests/simple.rs new file mode 100644 index 0000000000..b4c58bedab --- /dev/null +++ b/crates/circuits/sha-macros/tests/simple.rs @@ -0,0 +1,17 @@ +use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_macros::ColsRef; + +#[derive(ColsRef)] +struct Test { + a: T, + b: [T; WORD_BITS], + c: [[T; WORD_BITS]; ROUNDS_PER_ROW], +} + +#[test] +fn simple() { + let input = [0; 1 + 32 + 32 * 4]; + let test: TestRef = TestRef::from::(&input); + println!("{}, {}, {}", test.a, test.b[0], test.b[1]); + println!("{}", test.c); +} diff --git a/crates/circuits/sha-macros/tests/work-vars.rs b/crates/circuits/sha-macros/tests/work-vars.rs new file mode 100644 index 0000000000..e145bfffb1 --- /dev/null +++ b/crates/circuits/sha-macros/tests/work-vars.rs @@ -0,0 +1,28 @@ +use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_macros::ColsRef; + +#[repr(C)] +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaWorkVarsCols< + T, + const WORD_BITS: usize, + const ROUNDS_PER_ROW: usize, + const WORD_U16S: usize, +> { + /// `a` and `e` after each iteration as 32-bits + pub a: [[T; WORD_BITS]; ROUNDS_PER_ROW], + pub e: [[T; WORD_BITS]; ROUNDS_PER_ROW], + /// The carry's used for addition during each iteration when computing `a` and `e` + pub carry_a: [[T; WORD_U16S]; ROUNDS_PER_ROW], + pub carry_e: [[T; WORD_U16S]; ROUNDS_PER_ROW], +} + +#[test] +fn work_vars() { + let input = [2; 32 * 4 + 32 * 4 + 2 * 4 + 2 * 4]; + let test: ShaWorkVarsColsRef = ShaWorkVarsColsRef::from::(&input); + println!( + "{:?}\n{:?}\n{:?}\n{:?}", + test.a, test.e, test.carry_a, test.carry_e + ); +} diff --git a/crates/circuits/sha256-air/src/config.rs b/crates/circuits/sha256-air/src/config.rs new file mode 100644 index 0000000000..9ea7481d60 --- /dev/null +++ b/crates/circuits/sha256-air/src/config.rs @@ -0,0 +1,321 @@ +use std::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + +pub trait ShaConfig: Send + Sync + Clone { + type Word: 'static + + Shr + + Shl + + BitAnd + + Not + + BitXor + + BitOr + + RotateRight + + WrappingAdd + + PartialEq + + From + + TryInto + + Copy + + Send + + Sync; + /// Number of bits in a SHA word + const WORD_BITS: usize; + /// Number of 16-bit limbs in a SHA word + const WORD_U16S: usize = Self::WORD_BITS / 16; + /// Number of 8-bit limbs in a SHA word + const WORD_U8S: usize = Self::WORD_BITS / 8; + /// Number of words in a SHA block + const BLOCK_WORDS: usize; + /// Number of cells in a SHA block + const BLOCK_U8S: usize = Self::BLOCK_WORDS * Self::WORD_U8S; + /// Number of bits in a SHA block + const BLOCK_BITS: usize = Self::BLOCK_WORDS * Self::WORD_BITS; + /// Number of rows per block + const ROWS_PER_BLOCK: usize; + /// Number of rounds per row + const ROUNDS_PER_ROW: usize; + /// Number of rounds per row minus one (needed for one of the column structs) + const ROUNDS_PER_ROW_MINUS_ONE: usize = Self::ROUNDS_PER_ROW - 1; + /// Number of rounds per block + const ROUNDS_PER_BLOCK: usize; + /// Number of words in a SHA hash + const HASH_WORDS: usize; + /// Number of vars needed to encode the row index with [Encoder] + const ROW_VAR_CNT: usize; + + /// Width of the ShaRoundCols + const ROUND_WIDTH: usize = Self::FLAGS_WIDTH + + Self::WORK_VARS_WIDTH + + Self::MESSAGE_HELPER_WIDTH + + Self::MESSAGE_SCHEDULE_WIDTH; + /// Width of the ShaDigestCols + const DIGEST_WIDTH: usize = Self::FLAGS_WIDTH + + Self::WORK_VARS_WIDTH + + Self::MESSAGE_HELPER_WIDTH + + Self::MESSAGE_SCHEDULE_WIDTH + + Self::WORD_U8S * Self::HASH_WORDS + + Self::WORD_U16S * Self::HASH_WORDS; + /// Width of the ShaFlagsCols + const FLAGS_WIDTH: usize = Self::ROW_VAR_CNT + 6; + /// Width of the ShaWorkVarsCols + const WORK_VARS_WIDTH: usize = + 2 * Self::WORD_BITS * Self::ROUNDS_PER_ROW + 2 * Self::WORD_U16S * Self::ROUNDS_PER_ROW; + // Width of the ShaMessageHelperCols + const MESSAGE_HELPER_WIDTH: usize = + Self::WORD_U8S * (Self::ROUNDS_PER_ROW - 1) + 3 * Self::WORD_U16S * Self::ROUNDS_PER_ROW; + /// Width of the ShaMessageScheduleCols + const MESSAGE_SCHEDULE_WIDTH: usize = + Self::WORD_BITS * Self::ROUNDS_PER_ROW + Self::WORD_U8S * Self::ROUNDS_PER_ROW; + + /// Size of the buffer of the first 4 rows of a block (each row's size) + const BUFFER_SIZE: usize = Self::ROUNDS_PER_ROW * Self::WORD_U8S; + /// Width of the ShaCols + const WIDTH: usize = if Self::ROUND_WIDTH > Self::DIGEST_WIDTH { + Self::ROUND_WIDTH + } else { + Self::DIGEST_WIDTH + }; +} + +pub trait ShaPrecomputedValues { + // these should be appropirately sized for the config + fn get_invalid_carry_a(round_num: usize) -> &'static [u32]; + fn get_invalid_carry_e(round_num: usize) -> &'static [u32]; + fn get_k() -> &'static [T]; + fn get_h() -> &'static [T]; +} + +#[derive(Clone)] +pub struct Sha256Config; + +impl ShaConfig for Sha256Config { + // ==== Do not change these constants! ==== + type Word = u32; + /// Number of bits in a SHA256 word + const WORD_BITS: usize = 32; + /// Number of words in a SHA256 block + const BLOCK_WORDS: usize = 16; + /// Number of rows per block + const ROWS_PER_BLOCK: usize = 17; + /// Number of rounds per row + const ROUNDS_PER_ROW: usize = 4; + /// Number of rounds per block + const ROUNDS_PER_BLOCK: usize = 64; + /// Number of words in a SHA256 hash + const HASH_WORDS: usize = 8; + /// Number of vars needed to encode the row index with [Encoder] + const ROW_VAR_CNT: usize = 5; +} + +/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows +/// To optimize the trace generation of invalid rows, we have those values precomputed here +pub const SHA256_INVALID_CARRY_A: [[u32; Sha256Config::WORD_U16S]; Sha256Config::ROUNDS_PER_ROW] = [ + [1230919683, 1162494304], + [266373122, 1282901987], + [1519718403, 1008990871], + [923381762, 330807052], +]; +pub const SHA256_INVALID_CARRY_E: [[u32; Sha256Config::WORD_U16S]; Sha256Config::ROUNDS_PER_ROW] = [ + [204933122, 1994683449], + [443873282, 1544639095], + [719953922, 1888246508], + [194580482, 1075725211], +]; +/// SHA256 constant K's +pub const SHA256_K: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; +/// SHA256 initial hash values +pub const SHA256_H: [u32; 8] = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, +]; + +impl ShaPrecomputedValues for Sha256Config { + fn get_invalid_carry_a(round_num: usize) -> &'static [u32] { + &SHA256_INVALID_CARRY_A[round_num] + } + fn get_invalid_carry_e(round_num: usize) -> &'static [u32] { + &SHA256_INVALID_CARRY_E[round_num] + } + fn get_k() -> &'static [u32] { + &SHA256_K + } + fn get_h() -> &'static [u32] { + &SHA256_H + } +} + +#[derive(Clone)] +pub struct Sha512Config; + +impl ShaConfig for Sha512Config { + // ==== Do not change these constants! ==== + type Word = u64; + /// Number of bits in a SHA512 word + const WORD_BITS: usize = 64; + /// Number of words in a SHA512 block + const BLOCK_WORDS: usize = 16; + /// Number of rows per block + const ROWS_PER_BLOCK: usize = 21; // SHA-512 has 80 rounds, so needs more rows + /// Number of rounds per row + const ROUNDS_PER_ROW: usize = 4; + /// Number of rounds per block + const ROUNDS_PER_BLOCK: usize = 80; + /// Number of words in a SHA512 hash + const HASH_WORDS: usize = 8; + /// Number of vars needed to encode the row index with [Encoder] + const ROW_VAR_CNT: usize = 5; +} + +// TODO: fill in these constants + +/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows +/// To optimize the trace generation of invalid rows, we have those values precomputed here +pub(crate) const SHA512_INVALID_CARRY_A: [[u32; Sha512Config::WORD_U16S]; + Sha512Config::ROUNDS_PER_ROW] = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]; +pub(crate) const SHA512_INVALID_CARRY_E: [[u32; Sha512Config::WORD_U16S]; + Sha512Config::ROUNDS_PER_ROW] = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]; + +/// SHA512 constant K's +pub const SHA512_K: [u64; 80] = [ + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817, +]; +/// SHA512 initial hash values +pub const SHA512_H: [u64; 8] = [ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179, +]; + +impl ShaPrecomputedValues for Sha512Config { + fn get_invalid_carry_a(round_num: usize) -> &'static [u32] { + &SHA512_INVALID_CARRY_A[round_num] + } + fn get_invalid_carry_e(round_num: usize) -> &'static [u32] { + &SHA512_INVALID_CARRY_E[round_num] + } + fn get_k() -> &'static [u64] { + &SHA512_K + } + fn get_h() -> &'static [u64] { + &SHA512_H + } +} + +// Needed to avoid compile errors in utils.rs +// don't ask me why this doesn't inf loop +pub trait RotateRight { + fn rotate_right(self, n: u32) -> Self; +} +impl RotateRight for u32 { + fn rotate_right(self, n: u32) -> Self { + self.rotate_right(n) + } +} +impl RotateRight for u64 { + fn rotate_right(self, n: u32) -> Self { + self.rotate_right(n) + } +} +pub trait WrappingAdd { + fn wrapping_add(self, n: Self) -> Self; +} +impl WrappingAdd for u32 { + fn wrapping_add(self, n: u32) -> Self { + self.wrapping_add(n) + } +} +impl WrappingAdd for u64 { + fn wrapping_add(self, n: u64) -> Self { + self.wrapping_add(n) + } +} From f856c443c449c5297e6d8e4862fb481378702934 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 10 Feb 2025 16:00:40 -0500 Subject: [PATCH 2/7] Updated sha256 air to use sha-macros (ColsRef structs) --- crates/circuits/sha256-air/Cargo.toml | 2 + crates/circuits/sha256-air/src/air.rs | 467 +++++++------ crates/circuits/sha256-air/src/columns.rs | 133 ++-- crates/circuits/sha256-air/src/config.rs | 6 +- crates/circuits/sha256-air/src/lib.rs | 2 + crates/circuits/sha256-air/src/tests.rs | 106 +-- crates/circuits/sha256-air/src/trace.rs | 795 +++++++++++++++------- crates/circuits/sha256-air/src/utils.rs | 243 ++++--- 8 files changed, 1073 insertions(+), 681 deletions(-) diff --git a/crates/circuits/sha256-air/Cargo.toml b/crates/circuits/sha256-air/Cargo.toml index c376a1ffdd..9a8c76e16d 100644 --- a/crates/circuits/sha256-air/Cargo.toml +++ b/crates/circuits/sha256-air/Cargo.toml @@ -9,6 +9,8 @@ openvm-circuit-primitives = { workspace = true } openvm-stark-backend = { workspace = true } sha2 = { version = "0.10", features = ["compress"] } rand.workspace = true +openvm-sha-macros = { workspace = true } +ndarray = "0.16" [dev-dependencies] openvm-stark-sdk = { workspace = true } diff --git a/crates/circuits/sha256-air/src/air.rs b/crates/circuits/sha256-air/src/air.rs index e47aa96504..970185d01b 100644 --- a/crates/circuits/sha256-air/src/air.rs +++ b/crates/circuits/sha256-air/src/air.rs @@ -1,5 +1,6 @@ -use std::{array, borrow::Borrow, cmp::max, iter::once}; +use std::{cmp::max, iter::once, marker::PhantomData}; +use ndarray::s; use openvm_circuit_primitives::{ bitwise_op_lookup::BitwiseOperationLookupBus, encoder::Encoder, @@ -15,41 +16,43 @@ use openvm_stark_backend::{ use super::{ big_sig0_field, big_sig1_field, ch_field, compose, maj_field, small_sig0_field, - small_sig1_field, u32_into_limbs, Sha256DigestCols, Sha256RoundCols, SHA256_DIGEST_WIDTH, - SHA256_H, SHA256_HASH_WORDS, SHA256_K, SHA256_ROUNDS_PER_ROW, SHA256_ROUND_WIDTH, - SHA256_WORD_BITS, SHA256_WORD_U16S, SHA256_WORD_U8S, + small_sig1_field, +}; +use crate::{ + constraint_word_addition, word_into_u16_limbs, ShaConfig, ShaDigestColsRef, + ShaPrecomputedValues, ShaRoundColsRef, }; -use crate::constraint_word_addition; -/// Expects the message to be padded to a multiple of 512 bits +/// Expects the message to be padded to a multiple of C::BLOCK_WORDS * C::WORD_BITS bits #[derive(Clone, Debug)] -pub struct Sha256Air { +pub struct ShaAir> { pub bitwise_lookup_bus: BitwiseOperationLookupBus, pub row_idx_encoder: Encoder, /// Internal bus for self-interactions in this AIR. bus: PermutationCheckBus, + _phantom: PhantomData, } -impl Sha256Air { +impl> ShaAir { pub fn new(bitwise_lookup_bus: BitwiseOperationLookupBus, self_bus_idx: BusIndex) -> Self { Self { bitwise_lookup_bus, row_idx_encoder: Encoder::new(18, 2, false), bus: PermutationCheckBus::new(self_bus_idx), + _phantom: PhantomData, } } } -impl BaseAir for Sha256Air { +impl> BaseAir for ShaAir { fn width(&self) -> usize { - max( - Sha256RoundCols::::width(), - Sha256DigestCols::::width(), - ) + max(C::ROUND_WIDTH, C::DIGEST_WIDTH) } } -impl SubAir for Sha256Air { +impl> SubAir + for ShaAir +{ /// The start column for the sub-air to use type AirContext<'a> = usize @@ -69,7 +72,7 @@ impl SubAir for Sha256Air { } } -impl Sha256Air { +impl> ShaAir { /// Implements the single row constraints (i.e. imposes constraints only on local) /// Implements some sanity constraints on the row index, flags, and work variables fn eval_row(&self, builder: &mut AB, start_col: usize) { @@ -77,49 +80,49 @@ impl Sha256Air { let local = main.row_slice(0); // Doesn't matter which column struct we use here as we are only interested in the common columns - let local_cols: &Sha256DigestCols = - local[start_col..start_col + SHA256_DIGEST_WIDTH].borrow(); + let local_cols: ShaDigestColsRef = + ShaDigestColsRef::from::(&local[start_col..start_col + C::DIGEST_WIDTH]); let flags = &local_cols.flags; - builder.assert_bool(flags.is_round_row); - builder.assert_bool(flags.is_first_4_rows); - builder.assert_bool(flags.is_digest_row); - builder.assert_bool(flags.is_round_row + flags.is_digest_row); - builder.assert_bool(flags.is_last_block); + builder.assert_bool(*flags.is_round_row); + builder.assert_bool(*flags.is_first_4_rows); + builder.assert_bool(*flags.is_digest_row); + builder.assert_bool(*flags.is_round_row + *flags.is_digest_row); + builder.assert_bool(*flags.is_last_block); self.row_idx_encoder - .eval(builder, &local_cols.flags.row_idx); + .eval(builder, local_cols.flags.row_idx.to_slice().unwrap()); builder.assert_one( self.row_idx_encoder - .contains_flag_range::(&local_cols.flags.row_idx, 0..=17), + .contains_flag_range::(local_cols.flags.row_idx.to_slice().unwrap(), 0..=17), ); builder.assert_eq( self.row_idx_encoder - .contains_flag_range::(&local_cols.flags.row_idx, 0..=3), - flags.is_first_4_rows, + .contains_flag_range::(local_cols.flags.row_idx.to_slice().unwrap(), 0..=3), + *flags.is_first_4_rows, ); builder.assert_eq( self.row_idx_encoder - .contains_flag_range::(&local_cols.flags.row_idx, 0..=15), - flags.is_round_row, + .contains_flag_range::(local_cols.flags.row_idx.to_slice().unwrap(), 0..=15), + *flags.is_round_row, ); builder.assert_eq( self.row_idx_encoder - .contains_flag::(&local_cols.flags.row_idx, &[16]), - flags.is_digest_row, + .contains_flag::(local_cols.flags.row_idx.to_slice().unwrap(), &[16]), + *flags.is_digest_row, ); // If padding row we want the row_idx to be 17 builder.assert_eq( self.row_idx_encoder - .contains_flag::(&local_cols.flags.row_idx, &[17]), + .contains_flag::(local_cols.flags.row_idx.to_slice().unwrap(), &[17]), flags.is_padding_row(), ); // Constrain a, e, being composed of bits: we make sure a and e are always in the same place in the trace matrix // Note: this has to be true for every row, even padding rows - for i in 0..SHA256_ROUNDS_PER_ROW { - for j in 0..SHA256_WORD_BITS { - builder.assert_bool(local_cols.hash.a[i][j]); - builder.assert_bool(local_cols.hash.e[i][j]); + for i in 0..C::ROUNDS_PER_ROW { + for j in 0..C::WORD_BITS { + builder.assert_bool(local_cols.hash.a[[i, j]]); + builder.assert_bool(local_cols.hash.e[[i, j]]); } } } @@ -131,14 +134,15 @@ impl Sha256Air { fn eval_digest_row( &self, builder: &mut AB, - local: &Sha256RoundCols, - next: &Sha256DigestCols, + local: ShaRoundColsRef, + next: ShaDigestColsRef, ) { // Check that if this is the last row of a message or an inpadding row, the hash should be the [SHA256_H] - for i in 0..SHA256_ROUNDS_PER_ROW { - let a = next.hash.a[i].map(|x| x.into()); - let e = next.hash.e[i].map(|x| x.into()); - for j in 0..SHA256_WORD_U16S { + for i in 0..C::ROUNDS_PER_ROW { + let a = next.hash.a.row(i).mapv(|x| x.into()).to_vec(); + let e = next.hash.e.row(i).mapv(|x| x.into()).to_vec(); + + for j in 0..C::WORD_U16S { let a_limb = compose::(&a[j * 16..(j + 1) * 16], 1); let e_limb = compose::(&e[j * 16..(j + 1) * 16], 1); @@ -146,46 +150,52 @@ impl Sha256Air { builder .when( next.flags.is_padding_row() - + next.flags.is_last_block * next.flags.is_digest_row, + + *next.flags.is_last_block * *next.flags.is_digest_row, ) .assert_eq( a_limb, AB::Expr::from_canonical_u32( - u32_into_limbs::<2>(SHA256_H[SHA256_ROUNDS_PER_ROW - i - 1])[j], + word_into_u16_limbs::(C::get_h()[C::ROUNDS_PER_ROW - i - 1])[j], ), ); builder .when( next.flags.is_padding_row() - + next.flags.is_last_block * next.flags.is_digest_row, + + *next.flags.is_last_block * *next.flags.is_digest_row, ) .assert_eq( e_limb, AB::Expr::from_canonical_u32( - u32_into_limbs::<2>(SHA256_H[SHA256_ROUNDS_PER_ROW - i + 3])[j], + word_into_u16_limbs::(C::get_h()[C::ROUNDS_PER_ROW - i + 3])[j], ), ); } } // Check if last row of a non-last block, the `hash` should be equal to the final hash of the current block - for i in 0..SHA256_ROUNDS_PER_ROW { - let prev_a = next.hash.a[i].map(|x| x.into()); - let prev_e = next.hash.e[i].map(|x| x.into()); - let cur_a = next.final_hash[SHA256_ROUNDS_PER_ROW - i - 1].map(|x| x.into()); - - let cur_e = next.final_hash[SHA256_ROUNDS_PER_ROW - i + 3].map(|x| x.into()); - for j in 0..SHA256_WORD_U8S { + for i in 0..C::ROUNDS_PER_ROW { + let prev_a = next.hash.a.row(i).mapv(|x| x.into()).to_vec(); + let prev_e = next.hash.e.row(i).mapv(|x| x.into()).to_vec(); + let cur_a = next + .final_hash + .row(C::ROUNDS_PER_ROW - i - 1) + .mapv(|x| x.into()); + + let cur_e = next + .final_hash + .row(C::ROUNDS_PER_ROW - i + 3) + .mapv(|x| x.into()); + for j in 0..C::WORD_U8S { let prev_a_limb = compose::(&prev_a[j * 8..(j + 1) * 8], 1); let prev_e_limb = compose::(&prev_e[j * 8..(j + 1) * 8], 1); builder - .when(not(next.flags.is_last_block) * next.flags.is_digest_row) + .when(not(*next.flags.is_last_block) * *next.flags.is_digest_row) .assert_eq(prev_a_limb, cur_a[j].clone()); builder - .when(not(next.flags.is_last_block) * next.flags.is_digest_row) + .when(not(*next.flags.is_last_block) * *next.flags.is_digest_row) .assert_eq(prev_e_limb, cur_e[j].clone()); } } @@ -231,10 +241,10 @@ impl Sha256Air { let next = main.row_slice(1); // Doesn't matter what column structs we use here - let local_cols: &Sha256RoundCols = - local[start_col..start_col + SHA256_ROUND_WIDTH].borrow(); - let next_cols: &Sha256RoundCols = - next[start_col..start_col + SHA256_ROUND_WIDTH].borrow(); + let local_cols: ShaRoundColsRef = + ShaRoundColsRef::from::(&local[start_col..start_col + C::ROUND_WIDTH]); + let next_cols: ShaRoundColsRef = + ShaRoundColsRef::from::(&next[start_col..start_col + C::ROUND_WIDTH]); let local_is_padding_row = local_cols.flags.is_padding_row(); // Note that there will always be a padding row in the trace since the unpadded height is a multiple of 17. @@ -246,16 +256,16 @@ impl Sha256Air { // then the trace will be interpreted as containing multiple messages. builder .when(next_is_padding_row.clone()) - .when(local_cols.flags.is_digest_row) - .assert_one(local_cols.flags.is_last_block); + .when(*next_cols.flags.is_digest_row) + .assert_one(*next_cols.flags.is_last_block); // If we are in a round row, the next row cannot be a padding row builder - .when(local_cols.flags.is_round_row) + .when(*local_cols.flags.is_round_row) .assert_zero(next_is_padding_row.clone()); // The first row must be a round row builder .when_first_row() - .assert_one(local_cols.flags.is_round_row); + .assert_one(*local_cols.flags.is_round_row); // If we are in a padding row, the next row must also be a padding row builder .when_transition() @@ -263,28 +273,28 @@ impl Sha256Air { .assert_one(next_is_padding_row.clone()); // If we are in a digest row, the next row cannot be a digest row builder - .when(local_cols.flags.is_digest_row) - .assert_zero(next_cols.flags.is_digest_row); + .when(*local_cols.flags.is_digest_row) + .assert_zero(*next_cols.flags.is_digest_row); // Constrain how much the row index changes by // round->round: 1 // round->digest: 1 - // digest->round: -16 + // digest->round: -16 // TODO: sha512 // digest->padding: 1 // padding->padding: 0 // Other transitions are not allowed by the above constraints - let delta = local_cols.flags.is_round_row * AB::Expr::ONE - + local_cols.flags.is_digest_row - * next_cols.flags.is_round_row + let delta = *local_cols.flags.is_round_row * AB::Expr::ONE + + *local_cols.flags.is_digest_row + * *next_cols.flags.is_round_row * AB::Expr::from_canonical_u32(16) * AB::Expr::NEG_ONE - + local_cols.flags.is_digest_row * next_is_padding_row.clone() * AB::Expr::ONE; + + *local_cols.flags.is_digest_row * next_is_padding_row.clone() * AB::Expr::ONE; let local_row_idx = self.row_idx_encoder.flag_with_val::( - &local_cols.flags.row_idx, + local_cols.flags.row_idx.to_slice().unwrap(), &(0..18).map(|i| (i, i)).collect::>(), ); let next_row_idx = self.row_idx_encoder.flag_with_val::( - &next_cols.flags.row_idx, + next_cols.flags.row_idx.to_slice().unwrap(), &(0..18).map(|i| (i, i)).collect::>(), ); @@ -300,59 +310,61 @@ impl Sha256Air { // Global block index is 1 on first row builder .when_first_row() - .assert_one(local_cols.flags.global_block_idx); + .assert_one(*local_cols.flags.global_block_idx); // Global block index is constant on all rows in a block - builder.when(local_cols.flags.is_round_row).assert_eq( - local_cols.flags.global_block_idx, - next_cols.flags.global_block_idx, + builder.when(*local_cols.flags.is_round_row).assert_eq( + *local_cols.flags.global_block_idx, + *next_cols.flags.global_block_idx, ); // Global block index increases by 1 between blocks builder .when_transition() - .when(local_cols.flags.is_digest_row) - .when(next_cols.flags.is_round_row) + .when(*local_cols.flags.is_digest_row) + .when(*next_cols.flags.is_round_row) .assert_eq( - local_cols.flags.global_block_idx + AB::Expr::ONE, - next_cols.flags.global_block_idx, + *local_cols.flags.global_block_idx + AB::Expr::ONE, + *next_cols.flags.global_block_idx, ); // Global block index is 0 on padding rows builder .when(local_is_padding_row.clone()) - .assert_zero(local_cols.flags.global_block_idx); + .assert_zero(*local_cols.flags.global_block_idx); // Constrain the local block index // We set the local block index to 0 for padding rows // Local block index is constant on all rows in a block // and its value on padding rows is equal to its value on the first block - builder.when(not(local_cols.flags.is_digest_row)).assert_eq( - local_cols.flags.local_block_idx, - next_cols.flags.local_block_idx, - ); + builder + .when(not(*local_cols.flags.is_digest_row)) + .assert_eq( + *local_cols.flags.local_block_idx, + *next_cols.flags.local_block_idx, + ); // Local block index increases by 1 between blocks in the same message builder - .when(local_cols.flags.is_digest_row) - .when(not(local_cols.flags.is_last_block)) + .when(*local_cols.flags.is_digest_row) + .when(not(*local_cols.flags.is_last_block)) .assert_eq( - local_cols.flags.local_block_idx + AB::Expr::ONE, - next_cols.flags.local_block_idx, + *local_cols.flags.local_block_idx + AB::Expr::ONE, + *next_cols.flags.local_block_idx, ); // Local block index is 0 on padding rows // Combined with the above, this means that the local block index is 0 in the first block builder - .when(local_cols.flags.is_digest_row) - .when(local_cols.flags.is_last_block) - .assert_zero(next_cols.flags.local_block_idx); - - self.eval_message_schedule::(builder, local_cols, next_cols); - self.eval_work_vars::(builder, local_cols, next_cols); - let next_cols: &Sha256DigestCols = - next[start_col..start_col + SHA256_DIGEST_WIDTH].borrow(); + .when(*local_cols.flags.is_digest_row) + .when(*local_cols.flags.is_last_block) + .assert_zero(*next_cols.flags.local_block_idx); + + self.eval_message_schedule(builder, local_cols.clone(), next_cols.clone()); + self.eval_work_vars(builder, local_cols, next_cols); + let next_cols: ShaDigestColsRef = + ShaDigestColsRef::from::(&next[start_col..start_col + C::DIGEST_WIDTH]); self.eval_digest_row(builder, local_cols, next_cols); - let local_cols: &Sha256DigestCols = - local[start_col..start_col + SHA256_DIGEST_WIDTH].borrow(); - self.eval_prev_hash::(builder, local_cols, next_is_padding_row); + let local_cols: ShaDigestColsRef = + ShaDigestColsRef::from::(&local[start_col..start_col + C::DIGEST_WIDTH]); + self.eval_prev_hash(builder, local_cols, next_is_padding_row); } /// Constrains that the next block's `prev_hash` is equal to the current block's `hash` @@ -360,24 +372,37 @@ impl Sha256Air { fn eval_prev_hash( &self, builder: &mut AB, - local: &Sha256DigestCols, + local: ShaDigestColsRef, is_last_block_of_trace: AB::Expr, // note this indicates the last block of the trace, not the last block of the message ) { // Constrain that next block's `prev_hash` is equal to the current block's `hash` - let composed_hash: [[::Expr; SHA256_WORD_U16S]; SHA256_HASH_WORDS] = - array::from_fn(|i| { - let hash_bits = if i < SHA256_ROUNDS_PER_ROW { - local.hash.a[SHA256_ROUNDS_PER_ROW - 1 - i].map(|x| x.into()) + let composed_hash = (0..C::HASH_WORDS) + .map(|i| { + let hash_bits = if i < C::ROUNDS_PER_ROW { + local + .hash + .a + .row(C::ROUNDS_PER_ROW - 1 - i) + .mapv(|x| x.into()) + .to_vec() } else { - local.hash.e[SHA256_ROUNDS_PER_ROW + 3 - i].map(|x| x.into()) + local + .hash + .e + .row(C::ROUNDS_PER_ROW + 3 - i) + .mapv(|x| x.into()) + .to_vec() }; - array::from_fn(|j| compose::(&hash_bits[j * 16..(j + 1) * 16], 1)) - }); + (0..C::WORD_U16S) + .map(|j| compose::(&hash_bits[j * 16..(j + 1) * 16], 1)) + .collect::>() + }) + .collect::>(); // Need to handle the case if this is the very last block of the trace matrix let next_global_block_idx = select( is_last_block_of_trace, AB::Expr::ONE, - local.flags.global_block_idx + AB::Expr::ONE, + *local.flags.global_block_idx + AB::Expr::ONE, ); // The following interactions constrain certain values from block to block self.bus.send( @@ -386,44 +411,48 @@ impl Sha256Air { .into_iter() .flatten() .chain(once(next_global_block_idx)), - local.flags.is_digest_row, + *local.flags.is_digest_row, ); self.bus.receive( builder, local .prev_hash - .into_iter() .flatten() - .map(|x| x.into()) - .chain(once(local.flags.global_block_idx.into())), - local.flags.is_digest_row, + .mapv(|x| x.into()) + .into_iter() + .chain(once((*local.flags.global_block_idx).into())), + *local.flags.is_digest_row, ); } /// Constrain the message schedule additions for `next` row - /// Note: For every addition we need to constrain the following for each of [SHA256_WORD_U16S] limbs + /// Note: For every addition we need to constrain the following for each of [WORD_U16S] limbs /// sig_1(w_{t-2})[i] + w_{t-7}[i] + sig_0(w_{t-15})[i] + w_{t-16}[i] + carry_w[t][i-1] - carry_w[t][i] * 2^16 - w_t[i] == 0 /// Refer to [https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf] - fn eval_message_schedule( + fn eval_message_schedule<'a, AB: InteractionBuilder>( &self, builder: &mut AB, - local: &Sha256RoundCols, - next: &Sha256RoundCols, + local: ShaRoundColsRef<'a, AB::Var>, + next: ShaRoundColsRef<'a, AB::Var>, ) { // This `w` array contains 8 message schedule words - w_{idx}, ..., w_{idx+7} for some idx - let w = [local.message_schedule.w, next.message_schedule.w].concat(); + let w = ndarray::concatenate( + ndarray::Axis(0), + &[local.message_schedule.w, next.message_schedule.w], + ) + .unwrap(); // Constrain `w_3` for `next` row - for i in 0..SHA256_ROUNDS_PER_ROW - 1 { + for i in 0..C::ROUNDS_PER_ROW - 1 { // here we constrain the w_3 of the i_th word of the next row // w_3 of next is w[i+4-3] = w[i+1] - let w_3 = w[i + 1].map(|x| x.into()); - let expected_w_3 = next.schedule_helper.w_3[i]; - for j in 0..SHA256_WORD_U16S { + let w_3 = w.row(i + 1).mapv(|x| x.into()).to_vec(); + let expected_w_3 = next.schedule_helper.w_3.row(i); + for j in 0..C::WORD_U16S { let w_3_limb = compose::(&w_3[j * 16..(j + 1) * 16], 1); builder - .when(local.flags.is_round_row) + .when(*local.flags.is_round_row) .assert_eq(w_3_limb, expected_w_3[j].into()); } } @@ -433,159 +462,193 @@ impl Sha256Air { // Other rows should put the needed value in intermed_12 to make the below summation constraint hold let is_row_3_14 = self .row_idx_encoder - .contains_flag_range::(&next.flags.row_idx, 3..=14); + .contains_flag_range::(next.flags.row_idx.to_slice().unwrap(), 3..=14); // We will only constrain intermed_8 for rows [2, 13], and let it unconstrained for other rows let is_row_2_13 = self .row_idx_encoder - .contains_flag_range::(&next.flags.row_idx, 2..=13); - for i in 0..SHA256_ROUNDS_PER_ROW { + .contains_flag_range::(next.flags.row_idx.to_slice().unwrap(), 2..=13); + for i in 0..C::ROUNDS_PER_ROW { // w_idx - let w_idx = w[i].map(|x| x.into()); + let w_idx = w.row(i).mapv(|x| x.into()).to_vec(); // sig_0(w_{idx+1}) - let sig_w = small_sig0_field::(&w[i + 1]); - for j in 0..SHA256_WORD_U16S { + let sig_w = small_sig0_field::(w.row(i + 1).as_slice().unwrap()); + for j in 0..C::WORD_U16S { let w_idx_limb = compose::(&w_idx[j * 16..(j + 1) * 16], 1); let sig_w_limb = compose::(&sig_w[j * 16..(j + 1) * 16], 1); // We would like to constrain this only on rows 0..16, but we can't do a conditional check because the degree is already 3. // So we must fill in `intermed_4` with dummy values on rows 0 and 16 to ensure the constraint holds on these rows. builder.when_transition().assert_eq( - next.schedule_helper.intermed_4[i][j], + next.schedule_helper.intermed_4[[i, j]], w_idx_limb + sig_w_limb, ); builder.when(is_row_2_13.clone()).assert_eq( - next.schedule_helper.intermed_8[i][j], - local.schedule_helper.intermed_4[i][j], + next.schedule_helper.intermed_8[[i, j]], + local.schedule_helper.intermed_4[[i, j]], ); builder.when(is_row_3_14.clone()).assert_eq( - next.schedule_helper.intermed_12[i][j], - local.schedule_helper.intermed_8[i][j], + next.schedule_helper.intermed_12[[i, j]], + local.schedule_helper.intermed_8[[i, j]], ); } } // Constrain the message schedule additions for `next` row - for i in 0..SHA256_ROUNDS_PER_ROW { + for i in 0..C::ROUNDS_PER_ROW { // Note, here by w_{t} we mean the i_th word of the `next` row // w_{t-7} let w_7 = if i < 3 { - local.schedule_helper.w_3[i].map(|x| x.into()) + local.schedule_helper.w_3.row(i).mapv(|x| x.into()).to_vec() } else { - let w_3 = w[i - 3].map(|x| x.into()); - array::from_fn(|j| compose::(&w_3[j * 16..(j + 1) * 16], 1)) + let w_3 = w.row(i - 3).mapv(|x| x.into()).to_vec(); + (0..C::WORD_U16S) + .map(|j| compose::(&w_3[j * 16..(j + 1) * 16], 1)) + .collect::>() }; // sig_0(w_{t-15}) + w_{t-16} - let intermed_16 = local.schedule_helper.intermed_12[i].map(|x| x.into()); + let intermed_16 = local.schedule_helper.intermed_12.row(i).mapv(|x| x.into()); - let carries = array::from_fn(|j| { - next.message_schedule.carry_or_buffer[i][j * 2] - + AB::Expr::TWO * next.message_schedule.carry_or_buffer[i][j * 2 + 1] - }); + let carries = (0..C::WORD_U16S) + .map(|j| { + next.message_schedule.carry_or_buffer[[i, j * 2]] + + AB::Expr::TWO * next.message_schedule.carry_or_buffer[[i, j * 2 + 1]] + }) + .collect::>(); // Constrain `W_{idx} = sig_1(W_{idx-2}) + W_{idx-7} + sig_0(W_{idx-15}) + W_{idx-16}` - // We would like to constrain this only on rows 4..16, but we can't do a conditional check because the degree of sum is already 3 - // So we must fill in `intermed_12` with dummy values on rows 0..3 and 15 and 16 to ensure the constraint holds on rows - // 0..4 and 16. Note that the dummy value goes in the previous row to make the current row's constraint hold. - constraint_word_addition( + // We would like to constrain this only on rows 4..C::ROUND_ROWS, but we can't do a conditional check because the degree of sum is already 3 + // So we must fill in `intermed_12` with dummy values on rows 0..3 and C::ROUND_ROWS-1 and C::ROUND_ROWS to ensure the constraint holds on rows + // 0..4 and C::ROUND_ROWS. Note that the dummy value goes in the previous row to make the current row's constraint hold. + constraint_word_addition::<_, C>( // Note: here we can't do a conditional check because the degree of sum is already 3 &mut builder.when_transition(), - &[&small_sig1_field::(&w[i + 2])], - &[&w_7, &intermed_16], - &w[i + 4], + &[&small_sig1_field::( + w.row(i + 2).as_slice().unwrap(), + )], + &[&w_7, intermed_16.as_slice().unwrap()], + w.row(i + 4).as_slice().unwrap(), &carries, ); - for j in 0..SHA256_WORD_U16S { + for j in 0..C::WORD_U16S { // When on rows 4..16 message schedule carries should be 0 or 1 - let is_row_4_15 = next.flags.is_round_row - next.flags.is_first_4_rows; + let is_row_4_15 = *next.flags.is_round_row - *next.flags.is_first_4_rows; builder .when(is_row_4_15.clone()) - .assert_bool(next.message_schedule.carry_or_buffer[i][j * 2]); + .assert_bool(next.message_schedule.carry_or_buffer[[i, j * 2]]); builder .when(is_row_4_15) - .assert_bool(next.message_schedule.carry_or_buffer[i][j * 2 + 1]); + .assert_bool(next.message_schedule.carry_or_buffer[[i, j * 2 + 1]]); } // Constrain w being composed of bits - for j in 0..SHA256_WORD_BITS { + for j in 0..C::WORD_BITS { builder - .when(next.flags.is_round_row) - .assert_bool(next.message_schedule.w[i][j]); + .when(*next.flags.is_round_row) + .assert_bool(next.message_schedule.w[[i, j]]); } } } /// Constrain the work vars on `next` row according to the sha256 documentation /// Refer to [https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf] - fn eval_work_vars( + fn eval_work_vars<'a, AB: InteractionBuilder>( &self, builder: &mut AB, - local: &Sha256RoundCols, - next: &Sha256RoundCols, + local: ShaRoundColsRef<'a, AB::Var>, + next: ShaRoundColsRef<'a, AB::Var>, ) { - let a = [local.work_vars.a, next.work_vars.a].concat(); - let e = [local.work_vars.e, next.work_vars.e].concat(); - for i in 0..SHA256_ROUNDS_PER_ROW { - for j in 0..SHA256_WORD_U16S { + let a = + ndarray::concatenate(ndarray::Axis(0), &[local.work_vars.a, next.work_vars.a]).unwrap(); + let e = + ndarray::concatenate(ndarray::Axis(0), &[local.work_vars.e, next.work_vars.e]).unwrap(); + + for i in 0..C::ROUNDS_PER_ROW { + for j in 0..C::WORD_U16S { // Although we need carry_a <= 6 and carry_e <= 5, constraining carry_a, carry_e in [0, 2^8) is enough // to prevent overflow and ensure the soundness of the addition we want to check self.bitwise_lookup_bus - .send_range(local.work_vars.carry_a[i][j], local.work_vars.carry_e[i][j]) - .eval(builder, local.flags.is_round_row); + .send_range( + local.work_vars.carry_a[[i, j]], + local.work_vars.carry_e[[i, j]], + ) + .eval(builder, *local.flags.is_round_row); } - let w_limbs = array::from_fn(|j| { - compose::(&next.message_schedule.w[i][j * 16..(j + 1) * 16], 1) - * next.flags.is_round_row - }); - let k_limbs = array::from_fn(|j| { - self.row_idx_encoder.flag_with_val::( - &next.flags.row_idx, - &(0..16) - .map(|rw_idx| { - ( - rw_idx, - u32_into_limbs::( - SHA256_K[rw_idx * SHA256_ROUNDS_PER_ROW + i], - )[j] as usize, - ) - }) - .collect::>(), - ) - }); + let w_limbs = (0..C::WORD_U16S) + .map(|j| { + compose::( + next.message_schedule + .w + .slice(s![i, j * 16..(j + 1) * 16]) + .as_slice() + .unwrap(), + 1, + ) * *next.flags.is_round_row + }) + .collect::>(); + let k_limbs = (0..C::WORD_U16S) + .map(|j| { + self.row_idx_encoder.flag_with_val::( + next.flags.row_idx.to_slice().unwrap(), + &(0..16) + .map(|rw_idx| { + ( + rw_idx, + word_into_u16_limbs::( + C::get_k()[rw_idx * C::ROUNDS_PER_ROW + i], + )[j] as usize, + ) + }) + .collect::>(), + ) + }) + .collect::>(); // Constrain `a = h + sig_1(e) + ch(e, f, g) + K + W + sig_0(a) + Maj(a, b, c)` // We have to enforce this constraint on all rows since the degree of the constraint is already 3. // So, we must fill in `carry_a` with dummy values on digest rows to ensure the constraint holds. - constraint_word_addition( + constraint_word_addition::<_, C>( builder, &[ - &e[i].map(|x| x.into()), // previous `h` - &big_sig1_field::(&e[i + 3]), // sig_1 of previous `e` - &ch_field::(&e[i + 3], &e[i + 2], &e[i + 1]), // Ch of previous `e`, `f`, `g` - &big_sig0_field::(&a[i + 3]), // sig_0 of previous `a` - &maj_field::(&a[i + 3], &a[i + 2], &a[i + 1]), // Maj of previous a, b, c + e.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `h` + &big_sig1_field::(e.row(i + 3).as_slice().unwrap()), // sig_1 of previous `e` + &ch_field::( + e.row(i + 3).as_slice().unwrap(), + e.row(i + 2).as_slice().unwrap(), + e.row(i + 1).as_slice().unwrap(), + ), // Ch of previous `e`, `f`, `g` + &big_sig0_field::(a.row(i + 3).as_slice().unwrap()), // sig_0 of previous `a` + &maj_field::( + a.row(i + 3).as_slice().unwrap(), + a.row(i + 2).as_slice().unwrap(), + a.row(i + 1).as_slice().unwrap(), + ), // Maj of previous a, b, c ], - &[&w_limbs, &k_limbs], // K and W - &a[i + 4], // new `a` - &next.work_vars.carry_a[i], // carries of addition + &[&w_limbs, &k_limbs], // K and W + a.row(i + 4).as_slice().unwrap(), // new `a` + next.work_vars.carry_a.row(i).as_slice().unwrap(), // carries of addition ); // Constrain `e = d + h + sig_1(e) + ch(e, f, g) + K + W` // We have to enforce this constraint on all rows since the degree of the constraint is already 3. // So, we must fill in `carry_e` with dummy values on digest rows to ensure the constraint holds. - constraint_word_addition( + constraint_word_addition::<_, C>( builder, &[ - &a[i].map(|x| x.into()), // previous `d` - &e[i].map(|x| x.into()), // previous `h` - &big_sig1_field::(&e[i + 3]), // sig_1 of previous `e` - &ch_field::(&e[i + 3], &e[i + 2], &e[i + 1]), // Ch of previous `e`, `f`, `g` + &a.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `d` + &e.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `h` + &big_sig1_field::(e.row(i + 3).as_slice().unwrap()), // sig_1 of previous `e` + &ch_field::( + e.row(i + 3).as_slice().unwrap(), + e.row(i + 2).as_slice().unwrap(), + e.row(i + 1).as_slice().unwrap(), + ), // Ch of previous `e`, `f`, `g` ], - &[&w_limbs, &k_limbs], // K and W - &e[i + 4], // new `e` - &next.work_vars.carry_e[i], // carries of addition + &[&w_limbs, &k_limbs], // K and W + e.row(i + 4).as_slice().unwrap(), // new `e` + next.work_vars.carry_e.row(i).as_slice().unwrap(), // carries of addition ); } } diff --git a/crates/circuits/sha256-air/src/columns.rs b/crates/circuits/sha256-air/src/columns.rs index 173aca0943..43916e8afc 100644 --- a/crates/circuits/sha256-air/src/columns.rs +++ b/crates/circuits/sha256-air/src/columns.rs @@ -1,12 +1,10 @@ //! WARNING: the order of fields in the structs is important, do not change it -use openvm_circuit_primitives::{utils::not, AlignedBorrow}; +use openvm_circuit_primitives::utils::not; +use openvm_sha_macros::ColsRef; use openvm_stark_backend::p3_field::FieldAlgebra; -use super::{ - SHA256_HASH_WORDS, SHA256_ROUNDS_PER_ROW, SHA256_ROW_VAR_CNT, SHA256_WORD_BITS, - SHA256_WORD_U16S, SHA256_WORD_U8S, -}; +use crate::ShaConfig; /// In each SHA256 block: /// - First 16 rows use Sha256RoundCols @@ -26,77 +24,111 @@ use super::{ /// /// Note that the `Sha256WorkVarsCols` field it is used for different purposes in the two structs. #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256RoundCols { - pub flags: Sha256FlagsCols, +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaRoundCols< + T, + const WORD_BITS: usize, + const WORD_U8S: usize, + const WORD_U16S: usize, + const ROUNDS_PER_ROW: usize, + const ROUNDS_PER_ROW_MINUS_ONE: usize, + const ROW_VAR_CNT: usize, +> { + pub flags: ShaFlagsCols, /// Stores the current state of the working variables - pub work_vars: Sha256WorkVarsCols, - pub schedule_helper: Sha256MessageHelperCols, - pub message_schedule: Sha256MessageScheduleCols, + pub work_vars: ShaWorkVarsCols, + pub schedule_helper: + ShaMessageHelperCols, + pub message_schedule: ShaMessageScheduleCols, } #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256DigestCols { - pub flags: Sha256FlagsCols, +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaDigestCols< + T, + const WORD_BITS: usize, + const WORD_U8S: usize, + const WORD_U16S: usize, + const HASH_WORDS: usize, + const ROUNDS_PER_ROW: usize, + const ROUNDS_PER_ROW_MINUS_ONE: usize, + const ROW_VAR_CNT: usize, +> { + pub flags: ShaFlagsCols, /// Will serve as previous hash values for the next block. /// - on non-last blocks, this is the final hash of the current block /// - on last blocks, this is the initial state constants, SHA256_H. /// The work variables constraints are applied on all rows, so `carry_a` and `carry_e` /// must be filled in with dummy values to ensure these constraints hold. - pub hash: Sha256WorkVarsCols, - pub schedule_helper: Sha256MessageHelperCols, + pub hash: ShaWorkVarsCols, + pub schedule_helper: + ShaMessageHelperCols, /// The actual final hash values of the given block /// Note: the above `hash` will be equal to `final_hash` unless we are on the last block - pub final_hash: [[T; SHA256_WORD_U8S]; SHA256_HASH_WORDS], + pub final_hash: [[T; WORD_U8S]; HASH_WORDS], /// The final hash of the previous block /// Note: will be constrained using interactions with the chip itself - pub prev_hash: [[T; SHA256_WORD_U16S]; SHA256_HASH_WORDS], + pub prev_hash: [[T; WORD_U16S]; HASH_WORDS], } #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256MessageScheduleCols { - /// The message schedule words as 32-bit integers - /// The first 16 words will be the message data - pub w: [[T; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW], +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaMessageScheduleCols< + T, + const WORD_BITS: usize, + const ROUNDS_PER_ROW: usize, + const WORD_U8S: usize, +> { + /// The message schedule words as C::WORD_BITS-bit integers + /// The first 16 rows will be the message data + pub w: [[T; WORD_BITS]; ROUNDS_PER_ROW], /// Will be message schedule carries for rows 4..16 and a buffer for rows 0..4 to be used freely by wrapper chips /// Note: carries are 2 bit numbers represented using 2 cells as individual bits - pub carry_or_buffer: [[T; SHA256_WORD_U8S]; SHA256_ROUNDS_PER_ROW], + pub carry_or_buffer: [[T; WORD_U8S]; ROUNDS_PER_ROW], } #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256WorkVarsCols { +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaWorkVarsCols< + T, + const WORD_BITS: usize, + const ROUNDS_PER_ROW: usize, + const WORD_U16S: usize, +> { /// `a` and `e` after each iteration as 32-bits - pub a: [[T; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW], - pub e: [[T; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW], + pub a: [[T; WORD_BITS]; ROUNDS_PER_ROW], + pub e: [[T; WORD_BITS]; ROUNDS_PER_ROW], /// The carry's used for addition during each iteration when computing `a` and `e` - pub carry_a: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], - pub carry_e: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], + pub carry_a: [[T; WORD_U16S]; ROUNDS_PER_ROW], + pub carry_e: [[T; WORD_U16S]; ROUNDS_PER_ROW], } /// These are the columns that are used to help with the message schedule additions /// Note: these need to be correctly assigned for every row even on padding rows #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256MessageHelperCols { +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaMessageHelperCols< + T, + const WORD_U16S: usize, + const ROUNDS_PER_ROW: usize, + const ROUNDS_PER_ROW_MINUS_ONE: usize, +> { /// The following are used to move data forward to constrain the message schedule additions /// The value of `w` (message schedule word) from 3 rounds ago /// In general, `w_i` means `w` from `i` rounds ago - pub w_3: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW - 1], + pub w_3: [[T; WORD_U16S]; ROUNDS_PER_ROW_MINUS_ONE], /// Here intermediate(i) = w_i + sig_0(w_{i+1}) /// Intermed_t represents the intermediate t rounds ago /// This is needed to constrain the message schedule, since we can only constrain on two rows at a time - pub intermed_4: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], - pub intermed_8: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], - pub intermed_12: [[T; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW], + pub intermed_4: [[T; WORD_U16S]; ROUNDS_PER_ROW], + pub intermed_8: [[T; WORD_U16S]; ROUNDS_PER_ROW], + pub intermed_12: [[T; WORD_U16S]; ROUNDS_PER_ROW], } #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256FlagsCols { - /// A flag that indicates if the current row is among the first 16 rows of a block. +#[derive(Clone, Copy, Debug, ColsRef)] +pub struct ShaFlagsCols { + /// A flag that indicates if the current row is among the first C::ROUND_ROWS rows of a block. pub is_round_row: T, /// A flag that indicates if the current row is among the first 4 rows of a block. pub is_first_4_rows: T, @@ -106,7 +138,8 @@ pub struct Sha256FlagsCols { // This flag is only used in digest rows. pub is_last_block: T, /// We will encode the row index [0..17) using 5 cells - pub row_idx: [T; SHA256_ROW_VAR_CNT], + //#[length(ROW_VAR_CNT)] + pub row_idx: [T; ROW_VAR_CNT], /// The index of the current block in the trace starting at 1. /// Set to 0 on padding rows. pub global_block_idx: T, @@ -116,7 +149,9 @@ pub struct Sha256FlagsCols { pub local_block_idx: T, } -impl> Sha256FlagsCols { +impl, const ROW_VAR_CNT: usize> + ShaFlagsCols +{ // This refers to the padding rows that are added to the air to make the trace length a power of 2. // Not to be confused with the padding added to messages as part of the SHA hash function. pub fn is_not_padding_row(&self) -> O { @@ -132,3 +167,19 @@ impl> Sha256FlagsCols { not(self.is_not_padding_row()) } } + +// We need to implement this for the ColsRef type as well +impl<'a, O, T: Copy + core::ops::Add> ShaFlagsColsRef<'a, T> { + pub fn is_not_padding_row(&self) -> O { + *self.is_round_row + *self.is_digest_row + } + + // This refers to the padding rows that are added to the air to make the trace length a power of 2. + // Not to be confused with the padding added to messages as part of the SHA hash function. + pub fn is_padding_row(&self) -> O + where + O: FieldAlgebra, + { + not(self.is_not_padding_row()) + } +} diff --git a/crates/circuits/sha256-air/src/config.rs b/crates/circuits/sha256-air/src/config.rs index 9ea7481d60..93c2842ef4 100644 --- a/crates/circuits/sha256-air/src/config.rs +++ b/crates/circuits/sha256-air/src/config.rs @@ -30,12 +30,14 @@ pub trait ShaConfig: Send + Sync + Clone { const BLOCK_BITS: usize = Self::BLOCK_WORDS * Self::WORD_BITS; /// Number of rows per block const ROWS_PER_BLOCK: usize; - /// Number of rounds per row + /// Number of rounds per row. Must divide Self::ROUNDS_PER_BLOCK const ROUNDS_PER_ROW: usize; /// Number of rounds per row minus one (needed for one of the column structs) const ROUNDS_PER_ROW_MINUS_ONE: usize = Self::ROUNDS_PER_ROW - 1; - /// Number of rounds per block + /// Number of rounds per block. Must be a multiple of Self::ROUNDS_PER_ROW const ROUNDS_PER_BLOCK: usize; + /// Number of rows used to constrain rounds + const ROUND_ROWS: usize = Self::ROUNDS_PER_BLOCK / Self::ROUNDS_PER_ROW; /// Number of words in a SHA hash const HASH_WORDS: usize; /// Number of vars needed to encode the row index with [Encoder] diff --git a/crates/circuits/sha256-air/src/lib.rs b/crates/circuits/sha256-air/src/lib.rs index 48bdaee5f9..f103ae8903 100644 --- a/crates/circuits/sha256-air/src/lib.rs +++ b/crates/circuits/sha256-air/src/lib.rs @@ -3,11 +3,13 @@ mod air; mod columns; +mod config; mod trace; mod utils; pub use air::*; pub use columns::*; +pub use config::*; pub use trace::*; pub use utils::*; diff --git a/crates/circuits/sha256-air/src/tests.rs b/crates/circuits/sha256-air/src/tests.rs index 903b7b0695..669ab2a8bb 100644 --- a/crates/circuits/sha256-air/src/tests.rs +++ b/crates/circuits/sha256-air/src/tests.rs @@ -18,43 +18,52 @@ use openvm_stark_backend::{ rap::{get_air_name, BaseAirWithPublicValues, PartitionedBaseAir}, AirRef, Chip, ChipUsageGetter, }; -use openvm_stark_sdk::utils::create_seeded_rng; +use openvm_stark_sdk::{p3_baby_bear::BabyBear, utils::create_seeded_rng}; use rand::Rng; +use sha2::Sha256; use crate::{ - compose, small_sig0_field, Sha256Air, Sha256RoundCols, SHA256_BLOCK_U8S, SHA256_DIGEST_WIDTH, - SHA256_HASH_WORDS, SHA256_ROUNDS_PER_ROW, SHA256_ROUND_WIDTH, SHA256_ROWS_PER_BLOCK, - SHA256_WORD_U16S, SHA256_WORD_U8S, + compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, ShaFlagsColsRef, + ShaFlagsColsRefMut, ShaPrecomputedValues, }; // A wrapper AIR purely for testing purposes #[derive(Clone, Debug)] -pub struct Sha256TestAir { - pub sub_air: Sha256Air, +pub struct ShaTestAir> { + pub sub_air: ShaAir, } -impl BaseAirWithPublicValues for Sha256TestAir {} -impl PartitionedBaseAir for Sha256TestAir {} -impl BaseAir for Sha256TestAir { +impl> BaseAirWithPublicValues + for ShaTestAir +{ +} +impl> PartitionedBaseAir + for ShaTestAir +{ +} +impl> BaseAir for ShaTestAir { fn width(&self) -> usize { - >::width(&self.sub_air) + as BaseAir>::width(&self.sub_air) } } -impl Air for Sha256TestAir { +impl> Air + for ShaTestAir +{ fn eval(&self, builder: &mut AB) { self.sub_air.eval(builder, 0); } } // A wrapper Chip purely for testing purposes -pub struct Sha256TestChip { - pub air: Sha256TestAir, +pub struct ShaTestChip> { + pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - pub records: Vec<([u8; SHA256_BLOCK_U8S], bool)>, + pub records: Vec<(Vec, bool)>, // length of inner vec is BLOCK_U8S } -impl Chip for Sha256TestChip +impl + 'static> Chip + for ShaTestChip where Val: PrimeField32, { @@ -63,7 +72,7 @@ where } fn generate_air_proof_input(self) -> AirProofInput { - let trace = crate::generate_trace::>( + let trace = crate::generate_trace::, C>( &self.air.sub_air, self.bitwise_lookup_chip.clone(), self.records, @@ -72,38 +81,39 @@ where } } -impl ChipUsageGetter for Sha256TestChip { +impl> ChipUsageGetter for ShaTestChip { fn air_name(&self) -> String { get_air_name(&self.air) } fn current_trace_height(&self) -> usize { - self.records.len() * SHA256_ROWS_PER_BLOCK + self.records.len() * C::ROWS_PER_BLOCK } fn trace_width(&self) -> usize { - max(SHA256_ROUND_WIDTH, SHA256_DIGEST_WIDTH) + max(C::ROUND_WIDTH, C::DIGEST_WIDTH) } } const SELF_BUS_IDX: BusIndex = 28; -#[test] -fn rand_sha256_test() { +fn rand_sha_test + 'static>() { let mut rng = create_seeded_rng(); let tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); let bitwise_chip = SharedBitwiseOperationLookupChip::::new(bitwise_bus); let len = rng.gen_range(1..100); let random_records: Vec<_> = (0..len) - .map(|i| { + .map(|_| { ( - array::from_fn(|_| rng.gen::()), + (0..C::BLOCK_U8S) + .map(|_| rng.gen::()) + .collect::>(), rng.gen::() || i == len - 1, ) }) .collect(); - let chip = Sha256TestChip { - air: Sha256TestAir { - sub_air: Sha256Air::new(bitwise_bus, SELF_BUS_IDX), + let chip = ShaTestChip { + air: ShaTestAir { + sub_air: ShaAir::::new(bitwise_bus, SELF_BUS_IDX), }, bitwise_lookup_chip: bitwise_chip.clone(), records: random_records, @@ -113,15 +123,21 @@ fn rand_sha256_test() { tester.simple_test().expect("Verification failed"); } +#[test] +fn rand_sha256_test() { + rand_sha_test::(); +} + // A wrapper Chip to test that the final_hash is properly constrained. // This chip implements a malicious trace gen that violates the final_hash constraints. -pub struct Sha256TestBadFinalHashChip { - pub air: Sha256TestAir, +pub struct ShaTestBadFinalHashChip> { + pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - pub records: Vec<([u8; SHA256_BLOCK_U8S], bool)>, + pub records: Vec<(Vec, bool)>, // length of inner vec is C::BLOCK_U8S } -impl Chip for Sha256TestBadFinalHashChip +impl + 'static> Chip + for ShaTestBadFinalHashChip where Val: PrimeField32, { @@ -140,33 +156,35 @@ where // That is, every hash that this chip does will result in a final_hash of zero. for (i, row) in self.records.iter().enumerate() { if row.1 { - let last_digest_row_idx = (i + 1) * SHA256_ROWS_PER_BLOCK - 1; - let last_digest_row: &mut crate::Sha256DigestCols> = - trace.row_mut(last_digest_row_idx)[..SHA256_DIGEST_WIDTH].borrow_mut(); + let last_digest_row_idx = (i + 1) * C::ROWS_PER_BLOCK - 1; + let last_digest_row: crate::ShaDigestColsRefMut> = + ShaDigestColsRefMut::from::( + trace.row_mut(last_digest_row_idx)[..C::DIGEST_WIDTH].borrow_mut(), + ); // Set the final_hash to all zeros - for i in 0..SHA256_HASH_WORDS { - for j in 0..SHA256_WORD_U8S { - last_digest_row.final_hash[i][j] = Val::::ZERO; + for i in 0..C::HASH_WORDS { + for j in 0..C::WORD_U8S { + last_digest_row.final_hash[[i, j]] = Val::::ZERO; } } let (last_round_row, last_digest_row) = trace.row_pair_mut(last_digest_row_idx - 1, last_digest_row_idx); - let last_round_row: &mut crate::Sha256RoundCols> = - last_round_row.borrow_mut(); - let last_digest_row: &mut crate::Sha256RoundCols> = - last_digest_row.borrow_mut(); + let last_round_row: crate::ShaRoundColsRefMut> = + ShaRoundColsRefMut::from::(last_round_row.borrow_mut()); + let last_digest_row: crate::ShaRoundColsRefMut> = + ShaRoundColsRefMut::from::(last_digest_row.borrow_mut()); // fix the intermed_4 for the digest row generate_intermed_4(last_round_row, last_digest_row); } } - let non_padded_height = self.records.len() * SHA256_ROWS_PER_BLOCK; - let width = >>::width(&self.air.sub_air); + let non_padded_height = self.records.len() * C::ROWS_PER_BLOCK; + let width = as BaseAir>>::width(&self.air.sub_air); // recalculate the missing cells (second pass of generate_trace) trace.values[width..] - .par_chunks_mut(width * SHA256_ROWS_PER_BLOCK) - .take(non_padded_height / SHA256_ROWS_PER_BLOCK) + .par_chunks_mut(width * C::ROWS_PER_BLOCK) + .take(non_padded_height / C::ROWS_PER_BLOCK) .for_each(|chunk| { self.air.sub_air.generate_missing_cells(chunk, width, 0); }); diff --git a/crates/circuits/sha256-air/src/trace.rs b/crates/circuits/sha256-air/src/trace.rs index 3862cc0443..788c8eb22d 100644 --- a/crates/circuits/sha256-air/src/trace.rs +++ b/crates/circuits/sha256-air/src/trace.rs @@ -1,5 +1,6 @@ use std::{array, borrow::BorrowMut, ops::Range}; +use ndarray::{concatenate, ArrayViewMut1}; use openvm_circuit_primitives::{ bitwise_op_lookup::SharedBitwiseOperationLookupChip, utils::next_power_of_two_or_zero, }; @@ -7,34 +8,42 @@ use openvm_stark_backend::{ p3_air::BaseAir, p3_field::PrimeField32, p3_matrix::dense::RowMajorMatrix, p3_maybe_rayon::prelude::*, }; -use sha2::{compress256, digest::generic_array::GenericArray}; +use sha2::{compress256, compress512, digest::generic_array::GenericArray}; use super::{ - air::Sha256Air, big_sig0_field, big_sig1_field, ch_field, columns::Sha256RoundCols, compose, - get_flag_pt_array, maj_field, small_sig0_field, small_sig1_field, SHA256_BLOCK_WORDS, - SHA256_DIGEST_WIDTH, SHA256_HASH_WORDS, SHA256_ROUND_WIDTH, + air::ShaAir, big_sig0_field, big_sig1_field, ch_field, compose, get_flag_pt_array, maj_field, + small_sig0_field, small_sig1_field, ShaRoundColsRefMut, }; use crate::{ - big_sig0, big_sig1, ch, columns::Sha256DigestCols, limbs_into_u32, maj, small_sig0, small_sig1, - u32_into_limbs, SHA256_BLOCK_U8S, SHA256_BUFFER_SIZE, SHA256_H, SHA256_INVALID_CARRY_A, - SHA256_INVALID_CARRY_E, SHA256_K, SHA256_ROUNDS_PER_ROW, SHA256_ROWS_PER_BLOCK, - SHA256_WORD_BITS, SHA256_WORD_U16S, SHA256_WORD_U8S, + big_sig0, big_sig1, ch, limbs_into_u32, limbs_into_word, maj, small_sig0, small_sig1, + u32_into_bits, word_into_bits, word_into_u16_limbs, word_into_u8_limbs, ShaConfig, + ShaDigestColsRefMut, ShaPrecomputedValues, ShaRoundColsRef, WrappingAdd, }; /// The trace generation of SHA256 should be done in two passes. /// The first pass should do `get_block_trace` for every block and generate the invalid rows through `get_default_row` /// The second pass should go through all the blocks and call `generate_missing_cells` -impl Sha256Air { +impl> ShaAir { /// This function takes the input_message (padding not handled), the previous hash, /// and returns the new hash after processing the block input - pub fn get_block_hash( - prev_hash: &[u32; SHA256_HASH_WORDS], - input: [u8; SHA256_BLOCK_U8S], - ) -> [u32; SHA256_HASH_WORDS] { - let mut new_hash = *prev_hash; - let input_array = [GenericArray::from(input)]; - compress256(&mut new_hash, &input_array); - new_hash + pub fn get_block_hash(prev_hash: &[C::Word], input: Vec) -> Vec { + debug_assert!(prev_hash.len() == C::HASH_WORDS); + debug_assert!(input.len() == C::BLOCK_U8S); + let mut new_hash: [C::Word; 8] = prev_hash.try_into().unwrap(); + if C::WORD_BITS == 32 { + let hash_ptr: &mut [u32; 8] = unsafe { std::mem::transmute(&mut new_hash) }; + let input_array = [*GenericArray::::from_slice( + &input, + )]; + compress256(hash_ptr, &input_array); + } else if C::WORD_BITS == 64 { + let hash_ptr: &mut [u64; 8] = unsafe { std::mem::transmute(&mut new_hash) }; + let input_array = [*GenericArray::::from_slice( + &input, + )]; + compress512(hash_ptr, &input_array); + } + new_hash.to_vec() } /// This function takes a 512-bit chunk of the input message (padding not handled), the previous hash, @@ -49,84 +58,121 @@ impl Sha256Air { trace: &mut [F], trace_width: usize, trace_start_col: usize, - input: &[u32; SHA256_BLOCK_WORDS], + input: &[C::Word], bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - prev_hash: &[u32; SHA256_HASH_WORDS], + prev_hash: &[C::Word], is_last_block: bool, global_block_idx: u32, local_block_idx: u32, - buffer_vals: &[[F; SHA256_BUFFER_SIZE]; 4], + buffer_vals: &[&[F]; 4], ) { + debug_assert!(input.len() == C::BLOCK_WORDS); + debug_assert!(prev_hash.len() == C::HASH_WORDS); + debug_assert!(buffer_vals.iter().all(|x| x.len() == C::BUFFER_SIZE)); #[cfg(debug_assertions)] { - assert!(trace.len() == trace_width * SHA256_ROWS_PER_BLOCK); - assert!(trace_start_col + super::SHA256_WIDTH <= trace_width); + assert!(trace.len() == trace_width * C::ROWS_PER_BLOCK); + assert!(trace_start_col + C::WIDTH <= trace_width); assert!(self.bitwise_lookup_bus == bitwise_lookup_chip.bus()); if local_block_idx == 0 { - assert!(*prev_hash == SHA256_H); + assert!(*prev_hash == *C::get_h()); } } let get_range = |start: usize, len: usize| -> Range { start..start + len }; - let mut message_schedule = [0u32; 64]; + let mut message_schedule = vec![C::Word::from(0); C::ROUNDS_PER_BLOCK]; message_schedule[..input.len()].copy_from_slice(input); - let mut work_vars = *prev_hash; + let mut work_vars = prev_hash.to_vec(); for (i, row) in trace.chunks_exact_mut(trace_width).enumerate() { + // TODO: sha512 // doing the 64 rounds in 16 rows if i < 16 { - let cols: &mut Sha256RoundCols = - row[get_range(trace_start_col, SHA256_ROUND_WIDTH)].borrow_mut(); - cols.flags.is_round_row = F::ONE; - cols.flags.is_first_4_rows = if i < 4 { F::ONE } else { F::ZERO }; - cols.flags.is_digest_row = F::ZERO; - cols.flags.is_last_block = F::from_bool(is_last_block); - cols.flags.row_idx = - get_flag_pt_array(&self.row_idx_encoder, i).map(F::from_canonical_u32); - cols.flags.global_block_idx = F::from_canonical_u32(global_block_idx); - cols.flags.local_block_idx = F::from_canonical_u32(local_block_idx); + let mut cols: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( + &mut row[get_range(trace_start_col, C::ROUND_WIDTH)], + ); + *cols.flags.is_round_row = F::ONE; + *cols.flags.is_first_4_rows = if i < 4 { F::ONE } else { F::ZERO }; + *cols.flags.is_digest_row = F::ZERO; + *cols.flags.is_last_block = F::from_bool(is_last_block); + cols.flags + .row_idx + .iter_mut() + .zip( + get_flag_pt_array(&self.row_idx_encoder, i) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); + + *cols.flags.global_block_idx = F::from_canonical_u32(global_block_idx); + *cols.flags.local_block_idx = F::from_canonical_u32(local_block_idx); // W_idx = M_idx - if i < SHA256_ROWS_PER_BLOCK / SHA256_ROUNDS_PER_ROW { - for j in 0..SHA256_ROUNDS_PER_ROW { - cols.message_schedule.w[j] = u32_into_limbs::( - input[i * SHA256_ROUNDS_PER_ROW + j], - ) - .map(F::from_canonical_u32); - cols.message_schedule.carry_or_buffer[j] = - array::from_fn(|k| buffer_vals[i][j * SHA256_WORD_U16S * 2 + k]); + // TODO: fix this. should be smtg like `if i < C::BLOCK_WORDS` + if i < C::ROWS_PER_BLOCK / C::ROUNDS_PER_ROW { + for j in 0..C::ROUNDS_PER_ROW { + cols.message_schedule + .w + .row_mut(j) + .iter_mut() + .zip( + word_into_bits::(input[i * C::ROUNDS_PER_ROW + j]) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); + cols.message_schedule + .carry_or_buffer + .row_mut(j) + .iter_mut() + .zip( + (0..C::WORD_U16S).map(|k| buffer_vals[i][j * C::WORD_U16S * 2 + k]), + ) + .for_each(|(x, y)| *x = y); } } // W_idx = SIG1(W_{idx-2}) + W_{idx-7} + SIG0(W_{idx-15}) + W_{idx-16} else { - for j in 0..SHA256_ROUNDS_PER_ROW { - let idx = i * SHA256_ROUNDS_PER_ROW + j; - let nums: [u32; 4] = [ - small_sig1(message_schedule[idx - 2]), + for j in 0..C::ROUNDS_PER_ROW { + let idx = i * C::ROUNDS_PER_ROW + j; + let nums: [C::Word; 4] = [ + small_sig1::(message_schedule[idx - 2]), message_schedule[idx - 7], - small_sig0(message_schedule[idx - 15]), + small_sig0::(message_schedule[idx - 15]), message_schedule[idx - 16], ]; - let w: u32 = nums.iter().fold(0, |acc, &num| acc.wrapping_add(num)); - cols.message_schedule.w[j] = - u32_into_limbs::(w).map(F::from_canonical_u32); + let w: C::Word = nums + .iter() + .fold(C::Word::from(0), |acc, &num| acc.wrapping_add(num)); + cols.message_schedule + .w + .row_mut(j) + .iter_mut() + .zip( + word_into_bits::(w) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); let nums_limbs = nums .iter() - .map(|x| u32_into_limbs::(*x)) + .map(|x| word_into_u16_limbs::(*x)) .collect::>(); - let w_limbs = u32_into_limbs::(w); + let w_limbs = word_into_u16_limbs::(w); // fill in the carrys - for k in 0..SHA256_WORD_U16S { + for k in 0..C::WORD_U16S { let mut sum = nums_limbs.iter().fold(0, |acc, num| acc + num[k]); if k > 0 { - sum += (cols.message_schedule.carry_or_buffer[j][k * 2 - 2] - + F::TWO * cols.message_schedule.carry_or_buffer[j][k * 2 - 1]) - .as_canonical_u32(); + sum += (cols.message_schedule.carry_or_buffer[[j, k * 2 - 2]] + + F::TWO + * cols.message_schedule.carry_or_buffer[[j, k * 2 - 1]]) + .as_canonical_u32(); } let carry = (sum - w_limbs[k]) >> 16; - cols.message_schedule.carry_or_buffer[j][k * 2] = + cols.message_schedule.carry_or_buffer[[j, k * 2]] = F::from_canonical_u32(carry & 1); - cols.message_schedule.carry_or_buffer[j][k * 2 + 1] = + cols.message_schedule.carry_or_buffer[[j, k * 2 + 1]] = F::from_canonical_u32(carry >> 1); } // update the message schedule @@ -134,55 +180,82 @@ impl Sha256Air { } } // fill in the work variables - for j in 0..SHA256_ROUNDS_PER_ROW { + for j in 0..C::ROUNDS_PER_ROW { // t1 = h + SIG1(e) + ch(e, f, g) + K_idx + W_idx let t1 = [ work_vars[7], - big_sig1(work_vars[4]), - ch(work_vars[4], work_vars[5], work_vars[6]), - SHA256_K[i * SHA256_ROUNDS_PER_ROW + j], - limbs_into_u32(cols.message_schedule.w[j].map(|f| f.as_canonical_u32())), + big_sig1::(work_vars[4]), + ch::(work_vars[4], work_vars[5], work_vars[6]), + C::get_k()[i * C::ROUNDS_PER_ROW + j], + limbs_into_u32( + cols.message_schedule + .w + .row(j) + .map(|f| f.as_canonical_u32()) + .as_slice() + .unwrap(), + ) + .into(), ]; - let t1_sum: u32 = t1.iter().fold(0, |acc, &num| acc.wrapping_add(num)); + let t1_sum: C::Word = t1 + .iter() + .fold(C::Word::from(0), |acc, &num| acc.wrapping_add(num)); // t2 = SIG0(a) + maj(a, b, c) let t2 = [ - big_sig0(work_vars[0]), - maj(work_vars[0], work_vars[1], work_vars[2]), + big_sig0::(work_vars[0]), + maj::(work_vars[0], work_vars[1], work_vars[2]), ]; - let t2_sum: u32 = t2.iter().fold(0, |acc, &num| acc.wrapping_add(num)); + let t2_sum: C::Word = t2 + .iter() + .fold(C::Word::from(0), |acc, &num| acc.wrapping_add(num)); // e = d + t1 let e = work_vars[3].wrapping_add(t1_sum); - cols.work_vars.e[j] = - u32_into_limbs::(e).map(F::from_canonical_u32); - let e_limbs = u32_into_limbs::(e); + cols.work_vars + .e + .row_mut(j) + .iter_mut() + .zip( + word_into_bits::(e) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); + let e_limbs = word_into_u16_limbs::(e); // a = t1 + t2 let a = t1_sum.wrapping_add(t2_sum); - cols.work_vars.a[j] = - u32_into_limbs::(a).map(F::from_canonical_u32); - let a_limbs = u32_into_limbs::(a); + cols.work_vars + .a + .row_mut(j) + .iter_mut() + .zip( + word_into_bits::(a) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); + let a_limbs = word_into_u16_limbs::(a); // fill in the carrys - for k in 0..SHA256_WORD_U16S { - let t1_limb = t1.iter().fold(0, |acc, &num| { - acc + u32_into_limbs::(num)[k] - }); - let t2_limb = t2.iter().fold(0, |acc, &num| { - acc + u32_into_limbs::(num)[k] - }); - - let mut e_limb = - t1_limb + u32_into_limbs::(work_vars[3])[k]; + for k in 0..C::WORD_U16S { + let t1_limb = t1 + .iter() + .fold(0, |acc, &num| acc + word_into_u16_limbs::(num)[k]); + let t2_limb = t2 + .iter() + .fold(0, |acc, &num| acc + word_into_u16_limbs::(num)[k]); + + let mut e_limb = t1_limb + word_into_u16_limbs::(work_vars[3])[k]; let mut a_limb = t1_limb + t2_limb; if k > 0 { - a_limb += cols.work_vars.carry_a[j][k - 1].as_canonical_u32(); - e_limb += cols.work_vars.carry_e[j][k - 1].as_canonical_u32(); + a_limb += cols.work_vars.carry_a[[j, k - 1]].as_canonical_u32(); + e_limb += cols.work_vars.carry_e[[j, k - 1]].as_canonical_u32(); } let carry_a = (a_limb - a_limbs[k]) >> 16; let carry_e = (e_limb - e_limbs[k]) >> 16; - cols.work_vars.carry_a[j][k] = F::from_canonical_u32(carry_a); - cols.work_vars.carry_e[j][k] = F::from_canonical_u32(carry_e); + cols.work_vars.carry_a[[j, k]] = F::from_canonical_u32(carry_a); + cols.work_vars.carry_e[[j, k]] = F::from_canonical_u32(carry_e); bitwise_lookup_chip.request_range(carry_a, carry_e); } @@ -199,44 +272,79 @@ impl Sha256Air { // filling w_3 and intermed_4 here and the rest later if i > 0 { - for j in 0..SHA256_ROUNDS_PER_ROW { - let idx = i * SHA256_ROUNDS_PER_ROW + j; - let w_4 = u32_into_limbs::(message_schedule[idx - 4]); - let sig_0_w_3 = u32_into_limbs::(small_sig0( - message_schedule[idx - 3], - )); - cols.schedule_helper.intermed_4[j] = - array::from_fn(|k| F::from_canonical_u32(w_4[k] + sig_0_w_3[k])); - if j < SHA256_ROUNDS_PER_ROW - 1 { + for j in 0..C::ROUNDS_PER_ROW { + let idx = i * C::ROUNDS_PER_ROW + j; + let w_4 = word_into_u16_limbs::(message_schedule[idx - 4]); + let sig_0_w_3 = + word_into_u16_limbs::(small_sig0::(message_schedule[idx - 3])); + cols.schedule_helper + .intermed_4 + .row_mut(j) + .iter_mut() + .zip( + (0..C::WORD_U16S) + .map(|k| F::from_canonical_u32(w_4[k] + sig_0_w_3[k])) + .collect::>(), + ) + .for_each(|(x, y)| *x = y); + if j < C::ROUNDS_PER_ROW - 1 { let w_3 = message_schedule[idx - 3]; - cols.schedule_helper.w_3[j] = - u32_into_limbs::(w_3).map(F::from_canonical_u32); + cols.schedule_helper + .w_3 + .row_mut(j) + .iter_mut() + .zip( + word_into_u16_limbs::(w_3) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); } } } } // generate the digest row else { - let cols: &mut Sha256DigestCols = - row[get_range(trace_start_col, SHA256_DIGEST_WIDTH)].borrow_mut(); - for j in 0..SHA256_ROUNDS_PER_ROW - 1 { - let w_3 = message_schedule[i * SHA256_ROUNDS_PER_ROW + j - 3]; - cols.schedule_helper.w_3[j] = - u32_into_limbs::(w_3).map(F::from_canonical_u32); + let mut cols: ShaDigestColsRefMut = ShaDigestColsRefMut::from::( + &mut row[get_range(trace_start_col, C::DIGEST_WIDTH)], + ); + for j in 0..C::ROUNDS_PER_ROW - 1 { + let w_3 = message_schedule[i * C::ROUNDS_PER_ROW + j - 3]; + cols.schedule_helper + .w_3 + .row_mut(j) + .iter_mut() + .zip( + word_into_u16_limbs::(w_3) + .into_iter() + .map(F::from_canonical_u32) + .collect::>(), + ) + .for_each(|(x, y)| *x = y); } - cols.flags.is_round_row = F::ZERO; - cols.flags.is_first_4_rows = F::ZERO; - cols.flags.is_digest_row = F::ONE; - cols.flags.is_last_block = F::from_bool(is_last_block); - cols.flags.row_idx = - get_flag_pt_array(&self.row_idx_encoder, 16).map(F::from_canonical_u32); - cols.flags.global_block_idx = F::from_canonical_u32(global_block_idx); - - cols.flags.local_block_idx = F::from_canonical_u32(local_block_idx); - let final_hash: [u32; SHA256_HASH_WORDS] = - array::from_fn(|i| work_vars[i].wrapping_add(prev_hash[i])); - let final_hash_limbs: [[u32; SHA256_WORD_U8S]; SHA256_HASH_WORDS] = - array::from_fn(|i| u32_into_limbs::(final_hash[i])); + *cols.flags.is_round_row = F::ZERO; + *cols.flags.is_first_4_rows = F::ZERO; + *cols.flags.is_digest_row = F::ONE; + *cols.flags.is_last_block = F::from_bool(is_last_block); + cols.flags + .row_idx + .iter_mut() + .zip( + get_flag_pt_array(&self.row_idx_encoder, 16) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); + + *cols.flags.global_block_idx = F::from_canonical_u32(global_block_idx); + + *cols.flags.local_block_idx = F::from_canonical_u32(local_block_idx); + let final_hash: Vec = (0..C::HASH_WORDS) + .map(|i| work_vars[i].wrapping_add(prev_hash[i])) + .collect(); + let final_hash_limbs: Vec> = final_hash.iter().map(|i| + word_into_u8_limbs::(final_hash[i]) + ) // need to ensure final hash limbs are bytes, in order for // prev_hash[i] + work_vars[i] == final_hash[i] // to be constrained correctly @@ -245,55 +353,99 @@ impl Sha256Air { bitwise_lookup_chip.request_range(chunk[0], chunk[1]); } } - cols.final_hash = array::from_fn(|i| { - array::from_fn(|j| F::from_canonical_u32(final_hash_limbs[i][j])) - }); - cols.prev_hash = prev_hash - .map(|f| u32_into_limbs::(f).map(F::from_canonical_u32)); + cols.final_hash + .iter_mut() + .zip((0..C::HASH_WORDS).flat_map(|i| { + word_into_u8_limbs::(final_hash[i]) + .into_iter() + .map(F::from_canonical_u32) + })) + .for_each(|(x, y)| *x = y); + cols.prev_hash + .iter_mut() + .zip(prev_hash.into_iter().flat_map(|f| { + word_into_u16_limbs::(*f) + .into_iter() + .map(F::from_canonical_u32) + })) + .for_each(|(x, y)| *x = y); + let hash = if is_last_block { - SHA256_H.map(u32_into_limbs::) + C::get_h() + .iter() + .map(|x| word_into_bits::(*x)) + .collect::>() } else { cols.final_hash - .map(|f| limbs_into_u32(f.map(|x| x.as_canonical_u32()))) - .map(u32_into_limbs::) + .rows_mut() + .into_iter() + .map(|f| { + limbs_into_u32(f.map(|x| x.as_canonical_u32()).as_slice().unwrap()) + }) + .map(u32_into_bits::) + .collect() } - .map(|x| x.map(F::from_canonical_u32)); + .into_iter() + .map(|x| x.into_iter().map(F::from_canonical_u32)) + .collect::>(); - for i in 0..SHA256_ROUNDS_PER_ROW { - cols.hash.a[i] = hash[SHA256_ROUNDS_PER_ROW - i - 1]; - cols.hash.e[i] = hash[SHA256_ROUNDS_PER_ROW - i + 3]; + for i in 0..C::ROUNDS_PER_ROW { + cols.hash + .a + .row_mut(i) + .iter_mut() + .zip(hash[C::ROUNDS_PER_ROW - i - 1].clone()) + .for_each(|(x, y)| *x = y); + cols.hash + .e + .row_mut(i) + .iter_mut() + .zip(hash[C::ROUNDS_PER_ROW - i + 3].clone()) + .for_each(|(x, y)| *x = y); } } } - for i in 0..SHA256_ROWS_PER_BLOCK - 1 { + for i in 0..C::ROWS_PER_BLOCK - 1 { let rows = &mut trace[i * trace_width..(i + 2) * trace_width]; let (local, next) = rows.split_at_mut(trace_width); - let local_cols: &mut Sha256RoundCols = - local[get_range(trace_start_col, SHA256_ROUND_WIDTH)].borrow_mut(); - let next_cols: &mut Sha256RoundCols = - next[get_range(trace_start_col, SHA256_ROUND_WIDTH)].borrow_mut(); + let mut local_cols: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( + &mut local[get_range(trace_start_col, C::ROUND_WIDTH)], + ); + let mut next_cols: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( + &mut next[get_range(trace_start_col, C::ROUND_WIDTH)], + ); if i > 0 { - for j in 0..SHA256_ROUNDS_PER_ROW { - next_cols.schedule_helper.intermed_8[j] = - local_cols.schedule_helper.intermed_4[j]; - if (2..SHA256_ROWS_PER_BLOCK - 3).contains(&i) { - next_cols.schedule_helper.intermed_12[j] = - local_cols.schedule_helper.intermed_8[j]; + for j in 0..C::ROUNDS_PER_ROW { + next_cols + .schedule_helper + .intermed_8 + .row_mut(j) + .assign(&local_cols.schedule_helper.intermed_4.row(j)); + if (2..C::ROWS_PER_BLOCK - 3).contains(&i) { + next_cols + .schedule_helper + .intermed_12 + .row_mut(j) + .assign(&local_cols.schedule_helper.intermed_8.row(j)); } } } - if i == SHA256_ROWS_PER_BLOCK - 2 { + if i == C::ROWS_PER_BLOCK - 2 { // `next` is a digest row. // Fill in `carry_a` and `carry_e` with dummy values so the constraints on `a` and `e` hold. - Self::generate_carry_ae(local_cols, next_cols); + let const_local_cols = ShaRoundColsRef::::from_mut::(&local_cols); + Self::generate_carry_ae(const_local_cols.clone(), &mut next_cols); // Fill in row 16's `intermed_4` with dummy values so the message schedule constraints holds on that row - Self::generate_intermed_4(local_cols, next_cols); + Self::generate_intermed_4(const_local_cols, &mut next_cols); } if i <= 2 { // i is in 0..3. // Fill in `local.intermed_12` with dummy values so the message schedule constraints hold on rows 1..4. - Self::generate_intermed_12(local_cols, next_cols); + Self::generate_intermed_12( + &mut local_cols, + ShaRoundColsRef::::from_mut::(&next_cols), + ); } } } @@ -303,102 +455,166 @@ impl Sha256Air { /// And [`Self::generate_default_row`] is called for all invalid rows /// Will populate the missing values of `trace`, where the width of the trace is `trace_width` /// and the starting column for the `Sha256Air` is `trace_start_col`. - /// Note: `trace` needs to be the rows 1..17 of a block and the first row of the next block + /// Note: `trace` needs to be the rows 1..C::ROWS_PER_BLOCK of a block and the first row of the next block pub fn generate_missing_cells( &self, trace: &mut [F], trace_width: usize, trace_start_col: usize, ) { - // Here row_17 = next blocks row 0 - let rows_15_17 = &mut trace[14 * trace_width..17 * trace_width]; - let (row_15, row_16_17) = rows_15_17.split_at_mut(trace_width); - let (row_16, row_17) = row_16_17.split_at_mut(trace_width); - let cols_15: &mut Sha256RoundCols = - row_15[trace_start_col..trace_start_col + SHA256_ROUND_WIDTH].borrow_mut(); - let cols_16: &mut Sha256RoundCols = - row_16[trace_start_col..trace_start_col + SHA256_ROUND_WIDTH].borrow_mut(); - let cols_17: &mut Sha256RoundCols = - row_17[trace_start_col..trace_start_col + SHA256_ROUND_WIDTH].borrow_mut(); - // Fill in row 15's `intermed_12` with dummy values so the message schedule constraints holds on row 16 - Self::generate_intermed_12(cols_15, cols_16); - // Fill in row 16's `intermed_12` with dummy values so the message schedule constraints holds on the next block's row 0 - Self::generate_intermed_12(cols_16, cols_17); - // Fill in row 0's `intermed_4` with dummy values so the message schedule constraints holds on that row - Self::generate_intermed_4(cols_16, cols_17); + let rows = &mut trace[(C::ROUND_ROWS - 2) * trace_width..(C::ROUND_ROWS + 1) * trace_width]; + let (last_round_row, rows) = rows.split_at_mut(trace_width); + let (digest_row, next_block_first_row) = rows.split_at_mut(trace_width); + let mut cols_last_round_row: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( + &mut last_round_row[trace_start_col..trace_start_col + C::ROUND_WIDTH], + ); + let mut cols_digest_row: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( + &mut digest_row[trace_start_col..trace_start_col + C::ROUND_WIDTH], + ); + let mut cols_next_block_first_row: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( + &mut next_block_first_row[trace_start_col..trace_start_col + C::ROUND_WIDTH], + ); + // Fill in the last round row's `intermed_12` with dummy values so the message schedule constraints holds on row 16 + Self::generate_intermed_12(&mut cols_last_round_row, ShaRoundColsRef::from_mut::(&cols_digest_row)); + // Fill in the digest row's `intermed_12` with dummy values so the message schedule constraints holds on the next block's row 0 + Self::generate_intermed_12(&mut cols_digest_row, ShaRoundColsRef::from_mut::(&cols_next_block_first_row)); + // Fill in the next block's first row's `intermed_4` with dummy values so the message schedule constraints holds on that row + Self::generate_intermed_4(ShaRoundColsRef::from_mut::(&cols_digest_row), &mut cols_next_block_first_row); } /// Fills the `cols` as a padding row /// Note: we still need to correctly fill in the hash values, carries and intermeds - pub fn generate_default_row(self: &Sha256Air, cols: &mut Sha256RoundCols) { - cols.flags.is_round_row = F::ZERO; - cols.flags.is_first_4_rows = F::ZERO; - cols.flags.is_digest_row = F::ZERO; - - cols.flags.is_last_block = F::ZERO; - cols.flags.global_block_idx = F::ZERO; - cols.flags.row_idx = - get_flag_pt_array(&self.row_idx_encoder, 17).map(F::from_canonical_u32); - cols.flags.local_block_idx = F::ZERO; - - cols.message_schedule.w = [[F::ZERO; SHA256_WORD_BITS]; SHA256_ROUNDS_PER_ROW]; - cols.message_schedule.carry_or_buffer = - [[F::ZERO; SHA256_WORD_U16S * 2]; SHA256_ROUNDS_PER_ROW]; - - let hash = SHA256_H - .map(u32_into_limbs::) - .map(|x| x.map(F::from_canonical_u32)); - - for i in 0..SHA256_ROUNDS_PER_ROW { - cols.work_vars.a[i] = hash[SHA256_ROUNDS_PER_ROW - i - 1]; - cols.work_vars.e[i] = hash[SHA256_ROUNDS_PER_ROW - i + 3]; + pub fn generate_default_row(&self, mut cols: ShaRoundColsRefMut) { + *cols.flags.is_round_row = F::ZERO; + *cols.flags.is_first_4_rows = F::ZERO; + *cols.flags.is_digest_row = F::ZERO; + + *cols.flags.is_last_block = F::ZERO; + *cols.flags.global_block_idx = F::ZERO; + cols.flags + .row_idx + .iter_mut() + .zip( + get_flag_pt_array(&self.row_idx_encoder, 17) + .into_iter() + .map(F::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); + *cols.flags.local_block_idx = F::ZERO; + + cols.message_schedule + .w + .iter_mut() + .for_each(|x| *x = F::ZERO); + cols.message_schedule + .carry_or_buffer + .iter_mut() + .for_each(|x| *x = F::ZERO); + + let hash = C::get_h() + .iter() + .map(|x| word_into_bits::(*x)) + .map(|x| x.into_iter().map(F::from_canonical_u32).collect::>()) + .collect::>(); + + for i in 0..C::ROUNDS_PER_ROW { + cols.work_vars + .a + .row_mut(i) + .iter_mut() + .zip(hash[C::ROUNDS_PER_ROW - i - 1].clone()) + .for_each(|(x, y)| *x = y); + cols.work_vars + .e + .row_mut(i) + .iter_mut() + .zip(hash[C::ROUNDS_PER_ROW - i + 3].clone()) + .for_each(|(x, y)| *x = y); } - cols.work_vars.carry_a = array::from_fn(|i| { - array::from_fn(|j| F::from_canonical_u32(SHA256_INVALID_CARRY_A[i][j])) - }); - cols.work_vars.carry_e = array::from_fn(|i| { - array::from_fn(|j| F::from_canonical_u32(SHA256_INVALID_CARRY_E[i][j])) - }); + cols.work_vars + .carry_a + .iter_mut() + .zip((0..C::ROUNDS_PER_ROW).flat_map(|i| { + (0..C::WORD_U16S) + .map(|j| F::from_canonical_u32(C::get_invalid_carry_a(i)[j])) + .collect::>() + })) + .for_each(|(x, y)| *x = y); + cols.work_vars + .carry_e + .iter_mut() + .zip((0..C::ROUNDS_PER_ROW).flat_map(|i| { + (0..C::WORD_U16S) + .map(|j| F::from_canonical_u32(C::get_invalid_carry_e(i)[j])) + .collect::>() + })) + .for_each(|(x, y)| *x = y); } /// The following functions do the calculations in native field since they will be called on padding rows /// which can overflow and we need to make sure it matches the AIR constraints /// Puts the correct carrys in the `next_row`, the resulting carrys can be out of bound - fn generate_carry_ae( - local_cols: &Sha256RoundCols, - next_cols: &mut Sha256RoundCols, + fn generate_carry_ae<'a, 'b, F: PrimeField32>( + local_cols: ShaRoundColsRef<'a, F>, + next_cols: &mut ShaRoundColsRefMut<'b, F>, ) { - let a = [local_cols.work_vars.a, next_cols.work_vars.a].concat(); - let e = [local_cols.work_vars.e, next_cols.work_vars.e].concat(); - for i in 0..SHA256_ROUNDS_PER_ROW { + let a = [ + local_cols + .work_vars + .a + .rows() + .into_iter() + .collect::>(), + next_cols.work_vars.a.rows().into_iter().collect::>(), + ] + .concat(); + let e = [ + local_cols + .work_vars + .e + .rows() + .into_iter() + .collect::>(), + next_cols.work_vars.e.rows().into_iter().collect::>(), + ] + .concat(); + for i in 0..C::ROUNDS_PER_ROW { let cur_a = a[i + 4]; - let sig_a = big_sig0_field::(&a[i + 3]); - let maj_abc = maj_field::(&a[i + 3], &a[i + 2], &a[i + 1]); + let sig_a = big_sig0_field::(a[i + 3].as_slice().unwrap()); + let maj_abc = maj_field::( + a[i + 3].as_slice().unwrap(), + a[i + 2].as_slice().unwrap(), + a[i + 1].as_slice().unwrap(), + ); let d = a[i]; let cur_e = e[i + 4]; - let sig_e = big_sig1_field::(&e[i + 3]); - let ch_efg = ch_field::(&e[i + 3], &e[i + 2], &e[i + 1]); + let sig_e = big_sig1_field::(e[i + 3].as_slice().unwrap()); + let ch_efg = ch_field::( + e[i + 3].as_slice().unwrap(), + e[i + 2].as_slice().unwrap(), + e[i + 1].as_slice().unwrap(), + ); let h = e[i]; - let t1 = [h, sig_e, ch_efg]; + let t1 = [h.to_vec(), sig_e, ch_efg.to_vec()]; let t2 = [sig_a, maj_abc]; - for j in 0..SHA256_WORD_U16S { + for j in 0..C::WORD_U16S { let t1_limb_sum = t1.iter().fold(F::ZERO, |acc, x| { acc + compose::(&x[j * 16..(j + 1) * 16], 1) }); let t2_limb_sum = t2.iter().fold(F::ZERO, |acc, x| { acc + compose::(&x[j * 16..(j + 1) * 16], 1) }); - let d_limb = compose::(&d[j * 16..(j + 1) * 16], 1); - let cur_a_limb = compose::(&cur_a[j * 16..(j + 1) * 16], 1); - let cur_e_limb = compose::(&cur_e[j * 16..(j + 1) * 16], 1); + let d_limb = compose::(&d.as_slice().unwrap()[j * 16..(j + 1) * 16], 1); + let cur_a_limb = compose::(&cur_a.as_slice().unwrap()[j * 16..(j + 1) * 16], 1); + let cur_e_limb = compose::(&cur_e.as_slice().unwrap()[j * 16..(j + 1) * 16], 1); let sum = d_limb + t1_limb_sum + if j == 0 { F::ZERO } else { - next_cols.work_vars.carry_e[i][j - 1] + next_cols.work_vars.carry_e[[i, j - 1]] } - cur_e_limb; let carry_e = sum * (F::from_canonical_u32(1 << 16).inverse()); @@ -408,118 +624,164 @@ impl Sha256Air { + if j == 0 { F::ZERO } else { - next_cols.work_vars.carry_a[i][j - 1] + next_cols.work_vars.carry_a[[i, j - 1]] } - cur_a_limb; let carry_a = sum * (F::from_canonical_u32(1 << 16).inverse()); - next_cols.work_vars.carry_e[i][j] = carry_e; - next_cols.work_vars.carry_a[i][j] = carry_a; + next_cols.work_vars.carry_e[[i, j]] = carry_e; + next_cols.work_vars.carry_a[[i, j]] = carry_a; } } } /// Puts the correct intermed_4 in the `next_row` - fn generate_intermed_4( - local_cols: &Sha256RoundCols, - next_cols: &mut Sha256RoundCols, + fn generate_intermed_4<'a, 'b, F: PrimeField32>( + local_cols: ShaRoundColsRef<'a, F>, + next_cols: &mut ShaRoundColsRefMut<'b, F>, ) { - let w = [local_cols.message_schedule.w, next_cols.message_schedule.w].concat(); - let w_limbs: Vec<[F; SHA256_WORD_U16S]> = w + let w = [ + local_cols + .message_schedule + .w + .rows() + .into_iter() + .collect::>(), + next_cols + .message_schedule + .w + .rows() + .into_iter() + .collect::>(), + ] + .concat(); + let w_limbs: Vec> = w .iter() - .map(|x| array::from_fn(|i| compose::(&x[i * 16..(i + 1) * 16], 1))) + .map(|x| { + (0..C::WORD_U16S) + .map(|i| compose::(&x.as_slice().unwrap()[i * 16..(i + 1) * 16], 1)) + .collect::>() + }) .collect(); - for i in 0..SHA256_ROUNDS_PER_ROW { - let sig_w = small_sig0_field::(&w[i + 1]); - let sig_w_limbs: [F; SHA256_WORD_U16S] = - array::from_fn(|j| compose::(&sig_w[j * 16..(j + 1) * 16], 1)); + for i in 0..C::ROUNDS_PER_ROW { + let sig_w = small_sig0_field::(w[i + 1].as_slice().unwrap()); + let sig_w_limbs: Vec = (0..C::WORD_U16S) + .map(|j| compose::(&sig_w[j * 16..(j + 1) * 16], 1)) + .collect(); for (j, sig_w_limb) in sig_w_limbs.iter().enumerate() { - next_cols.schedule_helper.intermed_4[i][j] = w_limbs[i][j] + *sig_w_limb; + next_cols.schedule_helper.intermed_4[[i, j]] = w_limbs[i][j] + *sig_w_limb; } } } /// Puts the needed intermed_12 in the `local_row` - fn generate_intermed_12( - local_cols: &mut Sha256RoundCols, - next_cols: &Sha256RoundCols, + fn generate_intermed_12<'a, 'b, F: PrimeField32>( + local_cols: &mut ShaRoundColsRefMut<'a, F>, + next_cols: ShaRoundColsRef<'b, F>, ) { - let w = [local_cols.message_schedule.w, next_cols.message_schedule.w].concat(); - let w_limbs: Vec<[F; SHA256_WORD_U16S]> = w + let w = [ + local_cols + .message_schedule + .w + .rows() + .into_iter() + .collect::>(), + next_cols + .message_schedule + .w + .rows() + .into_iter() + .collect::>(), + ] + .concat(); + let w_limbs: Vec> = w .iter() - .map(|x| array::from_fn(|i| compose::(&x[i * 16..(i + 1) * 16], 1))) + .map(|x| { + (0..C::WORD_U16S) + .map(|i| compose::(&x.as_slice().unwrap()[i * 16..(i + 1) * 16], 1)) + .collect::>() + }) .collect(); - for i in 0..SHA256_ROUNDS_PER_ROW { + for i in 0..C::ROUNDS_PER_ROW { // sig_1(w_{t-2}) - let sig_w_2: [F; SHA256_WORD_U16S] = array::from_fn(|j| { - compose::(&small_sig1_field::(&w[i + 2])[j * 16..(j + 1) * 16], 1) - }); + let sig_w_2: Vec = (0..C::WORD_U16S) + .map(|j| { + compose::( + &small_sig1_field::(w[i + 2].as_slice().unwrap())[j * 16..(j + 1) * 16], + 1, + ) + }) + .collect(); // w_{t-7} let w_7 = if i < 3 { - local_cols.schedule_helper.w_3[i] + local_cols.schedule_helper.w_3.row(i).to_slice().unwrap() } else { - w_limbs[i - 3] + w_limbs[i - 3].as_slice() }; // w_t - let w_cur = w_limbs[i + 4]; - for j in 0..SHA256_WORD_U16S { - let carry = next_cols.message_schedule.carry_or_buffer[i][j * 2] - + F::TWO * next_cols.message_schedule.carry_or_buffer[i][j * 2 + 1]; + let w_cur = w_limbs[i + 4].as_slice(); + for j in 0..C::WORD_U16S { + let carry = next_cols.message_schedule.carry_or_buffer[[i, j * 2]] + + F::TWO * next_cols.message_schedule.carry_or_buffer[[i, j * 2 + 1]]; let sum = sig_w_2[j] + w_7[j] - carry * F::from_canonical_u32(1 << 16) - w_cur[j] + if j > 0 { - next_cols.message_schedule.carry_or_buffer[i][j * 2 - 2] + next_cols.message_schedule.carry_or_buffer[[i, j * 2 - 2]] + F::from_canonical_u32(2) - * next_cols.message_schedule.carry_or_buffer[i][j * 2 - 1] + * next_cols.message_schedule.carry_or_buffer[[i, j * 2 - 1]] } else { F::ZERO }; - local_cols.schedule_helper.intermed_12[i][j] = -sum; + local_cols.schedule_helper.intermed_12[[i, j]] = -sum; } } } } /// `records` consists of pairs of `(input_block, is_last_block)`. -pub fn generate_trace( - sub_air: &Sha256Air, +pub fn generate_trace>( + sub_air: &ShaAir, bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - records: Vec<([u8; SHA256_BLOCK_U8S], bool)>, + records: Vec<(Vec, bool)>, ) -> RowMajorMatrix { - let non_padded_height = records.len() * SHA256_ROWS_PER_BLOCK; + for (input, _) in &records { + debug_assert!(input.len() == C::BLOCK_U8S); + } + + let non_padded_height = records.len() * C::ROWS_PER_BLOCK; let height = next_power_of_two_or_zero(non_padded_height); - let width = >::width(sub_air); + let width = as BaseAir>::width(sub_air); let mut values = F::zero_vec(height * width); - struct BlockContext { - prev_hash: [u32; 8], + struct BlockContext { + prev_hash: Vec, // HASH_WORDS local_block_idx: u32, global_block_idx: u32, - input: [u8; SHA256_BLOCK_U8S], + input: Vec, // BLOCK_U8S is_last_block: bool, } - let mut block_ctx: Vec = Vec::with_capacity(records.len()); - let mut prev_hash = SHA256_H; + let mut block_ctx: Vec> = Vec::with_capacity(records.len()); + let mut prev_hash = C::get_h().to_vec(); let mut local_block_idx = 0; let mut global_block_idx = 1; for (input, is_last_block) in records { block_ctx.push(BlockContext { - prev_hash, + prev_hash: prev_hash.clone(), local_block_idx, global_block_idx, - input, + input: input.clone(), is_last_block, }); global_block_idx += 1; if is_last_block { local_block_idx = 0; - prev_hash = SHA256_H; + prev_hash = C::get_h().to_vec(); } else { local_block_idx += 1; - prev_hash = Sha256Air::get_block_hash(&prev_hash, input); + prev_hash = ShaAir::::get_block_hash(&prev_hash, input); } } // first pass values - .par_chunks_exact_mut(width * SHA256_ROWS_PER_BLOCK) + .par_chunks_exact_mut(width * C::ROWS_PER_BLOCK) .zip(block_ctx) .for_each(|(block, ctx)| { let BlockContext { @@ -529,11 +791,18 @@ pub fn generate_trace( input, is_last_block, } = ctx; - let input_words = array::from_fn(|i| { - limbs_into_u32::(array::from_fn(|j| { - input[(i + 1) * SHA256_WORD_U8S - j - 1] as u32 - })) - }); + let input_words = (0..C::BLOCK_WORDS) + .map(|i| { + limbs_into_word::( + &(0..C::WORD_U8S).map(|j| + input[((i + 1) * C::WORD_U8S - j - 1] + ) + .collect::>(), + ) + }) + .collect::>(); + let empty_buffer = vec![F::ZERO; C::BUFFER_SIZE]; + let buffer_vals = [empty_buffer.as_slice(); 4]; sub_air.generate_block_trace( block, width, @@ -544,20 +813,20 @@ pub fn generate_trace( is_last_block, global_block_idx, local_block_idx, - &[[F::ZERO; 16]; 4], + &buffer_vals, ); }); // second pass: padding rows values[width * non_padded_height..] .par_chunks_mut(width) .for_each(|row| { - let cols: &mut Sha256RoundCols = row.borrow_mut(); + let cols: ShaRoundColsRefMut = ShaRoundColsRefMut::from::(row); sub_air.generate_default_row(cols); }); // second pass: non-padding rows values[width..] - .par_chunks_mut(width * SHA256_ROWS_PER_BLOCK) - .take(non_padded_height / SHA256_ROWS_PER_BLOCK) + .par_chunks_mut(width * C::ROWS_PER_BLOCK) + .take(non_padded_height / C::ROWS_PER_BLOCK) .for_each(|chunk| { sub_air.generate_missing_cells(chunk, width, 0); }); diff --git a/crates/circuits/sha256-air/src/utils.rs b/crates/circuits/sha256-air/src/utils.rs index abf8b6e7f2..72dac93474 100644 --- a/crates/circuits/sha256-air/src/utils.rs +++ b/crates/circuits/sha256-air/src/utils.rs @@ -8,81 +8,64 @@ use openvm_circuit_primitives::{ use openvm_stark_backend::{p3_air::AirBuilder, p3_field::FieldAlgebra}; use rand::{rngs::StdRng, Rng}; -use super::{Sha256DigestCols, Sha256RoundCols}; +use crate::{RotateRight, ShaConfig}; -// ==== Do not change these constants! ==== -/// Number of bits in a SHA256 word -pub const SHA256_WORD_BITS: usize = 32; -/// Number of 16-bit limbs in a SHA256 word -pub const SHA256_WORD_U16S: usize = SHA256_WORD_BITS / 16; -/// Number of 8-bit limbs in a SHA256 word -pub const SHA256_WORD_U8S: usize = SHA256_WORD_BITS / 8; -/// Number of words in a SHA256 block -pub const SHA256_BLOCK_WORDS: usize = 16; -/// Number of cells in a SHA256 block -pub const SHA256_BLOCK_U8S: usize = SHA256_BLOCK_WORDS * SHA256_WORD_U8S; -/// Number of bits in a SHA256 block -pub const SHA256_BLOCK_BITS: usize = SHA256_BLOCK_WORDS * SHA256_WORD_BITS; -/// Number of rows per block -pub const SHA256_ROWS_PER_BLOCK: usize = 17; -/// Number of rounds per row -pub const SHA256_ROUNDS_PER_ROW: usize = 4; -/// Number of words in a SHA256 hash -pub const SHA256_HASH_WORDS: usize = 8; -/// Number of vars needed to encode the row index with [Encoder] -pub const SHA256_ROW_VAR_CNT: usize = 5; -/// Width of the Sha256RoundCols -pub const SHA256_ROUND_WIDTH: usize = Sha256RoundCols::::width(); -/// Width of the Sha256DigestCols -pub const SHA256_DIGEST_WIDTH: usize = Sha256DigestCols::::width(); -/// Size of the buffer of the first 4 rows of a block (each row's size) -pub const SHA256_BUFFER_SIZE: usize = SHA256_ROUNDS_PER_ROW * SHA256_WORD_U16S * 2; -/// Width of the Sha256Cols -pub const SHA256_WIDTH: usize = if SHA256_ROUND_WIDTH > SHA256_DIGEST_WIDTH { - SHA256_ROUND_WIDTH -} else { - SHA256_DIGEST_WIDTH -}; -/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows -/// To optimize the trace generation of invalid rows, we have those values precomputed here -pub(crate) const SHA256_INVALID_CARRY_A: [[u32; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW] = [ - [1230919683, 1162494304], - [266373122, 1282901987], - [1519718403, 1008990871], - [923381762, 330807052], -]; -pub(crate) const SHA256_INVALID_CARRY_E: [[u32; SHA256_WORD_U16S]; SHA256_ROUNDS_PER_ROW] = [ - [204933122, 1994683449], - [443873282, 1544639095], - [719953922, 1888246508], - [194580482, 1075725211], -]; -/// SHA256 constant K's -pub const SHA256_K: [u32; 64] = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -]; +/// Convert a word into a list of 8-bit limbs in little endian +pub fn word_into_u8_limbs(num: impl Into) -> Vec { + word_into_limbs::(num.into(), C::WORD_U8S) +} -/// SHA256 initial hash values -pub const SHA256_H: [u32; 8] = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, -]; +/// Convert a word into a list of 16-bit limbs in little endian +pub fn word_into_u16_limbs(num: impl Into) -> Vec { + word_into_limbs::(num.into(), C::WORD_U16S) +} + +/// Convert a word into a list of 1-bit limbs in little endian +pub fn word_into_bits(num: impl Into) -> Vec { + word_into_limbs::(num.into(), C::WORD_BITS) +} + +/// Convert a word into a list of limbs in little endian +pub fn word_into_limbs(num: C::Word, num_limbs: usize) -> Vec { + let limb_bits = std::mem::size_of::() * 8 / num_limbs; + (0..num_limbs) + .map(|i| { + let shifted = num >> (limb_bits * i); + let mask: C::Word = ((1u32 << limb_bits) - 1).into(); + let masked = shifted & mask; + masked.try_into().unwrap() + }) + .collect() +} + +/// Convert a u32 into a list of 1-bit limbs in little endian +pub fn u32_into_bits(num: u32) -> Vec { + let limb_bits = 32 / C::WORD_BITS; + (0..C::WORD_BITS) + .map(|i| (num >> (limb_bits * i)) & ((1 << limb_bits) - 1)) + .collect() +} +// TODO: delete +/* /// Convert a u32 into a list of limbs in little endian pub fn u32_into_limbs(num: u32) -> [u32; NUM_LIMBS] { let limb_bits = 32 / NUM_LIMBS; array::from_fn(|i| (num >> (limb_bits * i)) & ((1 << limb_bits) - 1)) } +*/ + +/// Convert a list of limbs in little endian into a Word +pub fn limbs_into_word(limbs: &[u32]) -> C::Word { + let limb_bits = C::WORD_BITS / limbs.len(); + limbs.iter().rev().fold(C::Word::from(0), |acc, &limb| { + (acc << limb_bits) | limb.into() + }) +} /// Convert a list of limbs in little endian into a u32 -pub fn limbs_into_u32(limbs: [u32; NUM_LIMBS]) -> u32 { - let limb_bits = 32 / NUM_LIMBS; +pub fn limbs_into_u32(limbs: &[u32]) -> u32 { + let limb_bits = 32 / limbs.len(); limbs .iter() .rev() @@ -91,26 +74,24 @@ pub fn limbs_into_u32(limbs: [u32; NUM_LIMBS]) -> u32 { /// Rotates `bits` right by `n` bits, assumes `bits` is in little-endian #[inline] -pub(crate) fn rotr( - bits: &[impl Into + Clone; SHA256_WORD_BITS], - n: usize, -) -> [F; SHA256_WORD_BITS] { - array::from_fn(|i| bits[(i + n) % SHA256_WORD_BITS].clone().into()) +pub(crate) fn rotr(bits: &[impl Into + Clone], n: usize) -> Vec { + (0..bits.len()) + .map(|i| bits[(i + n) % bits.len()].clone().into()) + .collect() } /// Shifts `bits` right by `n` bits, assumes `bits` is in little-endian #[inline] -pub(crate) fn shr( - bits: &[impl Into + Clone; SHA256_WORD_BITS], - n: usize, -) -> [F; SHA256_WORD_BITS] { - array::from_fn(|i| { - if i + n < SHA256_WORD_BITS { - bits[i + n].clone().into() - } else { - F::ZERO - } - }) +pub(crate) fn shr(bits: &[impl Into + Clone], n: usize) -> Vec { + (0..bits.len()) + .map(|i| { + if i + n < bits.len() { + bits[i + n].clone().into() + } else { + F::ZERO + } + }) + .collect() } /// Computes x ^ y ^ z, where x, y, z are assumed to be boolean @@ -130,100 +111,99 @@ pub(crate) fn xor_bit( /// Computes x ^ y ^ z, where x, y, z are [SHA256_WORD_BITS] bit numbers #[inline] pub(crate) fn xor( - x: &[impl Into + Clone; SHA256_WORD_BITS], - y: &[impl Into + Clone; SHA256_WORD_BITS], - z: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { - array::from_fn(|i| xor_bit(x[i].clone(), y[i].clone(), z[i].clone())) + x: &[impl Into + Clone], + y: &[impl Into + Clone], + z: &[impl Into + Clone], +) -> Vec { + (0..x.len()) + .map(|i| xor_bit(x[i].clone(), y[i].clone(), z[i].clone())) + .collect() } /// Choose function from SHA256 #[inline] -pub fn ch(x: u32, y: u32, z: u32) -> u32 { +pub fn ch(x: C::Word, y: C::Word, z: C::Word) -> C::Word { (x & y) ^ ((!x) & z) } /// Computes Ch(x,y,z), where x, y, z are [SHA256_WORD_BITS] bit numbers #[inline] pub(crate) fn ch_field( - x: &[impl Into + Clone; SHA256_WORD_BITS], - y: &[impl Into + Clone; SHA256_WORD_BITS], - z: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { - array::from_fn(|i| select(x[i].clone(), y[i].clone(), z[i].clone())) + x: &[impl Into + Clone], + y: &[impl Into + Clone], + z: &[impl Into + Clone], +) -> Vec { + (0..x.len()) + .map(|i| select(x[i].clone(), y[i].clone(), z[i].clone())) + .collect() } /// Majority function from SHA256 -pub fn maj(x: u32, y: u32, z: u32) -> u32 { +pub fn maj(x: C::Word, y: C::Word, z: C::Word) -> C::Word { (x & y) ^ (x & z) ^ (y & z) } /// Computes Maj(x,y,z), where x, y, z are [SHA256_WORD_BITS] bit numbers #[inline] pub(crate) fn maj_field( - x: &[impl Into + Clone; SHA256_WORD_BITS], - y: &[impl Into + Clone; SHA256_WORD_BITS], - z: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { - array::from_fn(|i| { - let (x, y, z) = ( - x[i].clone().into(), - y[i].clone().into(), - z[i].clone().into(), - ); - x.clone() * y.clone() + x.clone() * z.clone() + y.clone() * z.clone() - F::TWO * x * y * z - }) + x: &[impl Into + Clone], + y: &[impl Into + Clone], + z: &[impl Into + Clone], +) -> Vec { + (0..x.len()) + .map(|i| { + let (x, y, z) = ( + x[i].clone().into(), + y[i].clone().into(), + z[i].clone().into(), + ); + x.clone() * y.clone() + x.clone() * z.clone() + y.clone() * z.clone() + - F::TWO * x * y * z + }) + .collect() } /// Big sigma_0 function from SHA256 -pub fn big_sig0(x: u32) -> u32 { +pub fn big_sig0(x: C::Word) -> C::Word { x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22) } /// Computes BigSigma0(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn big_sig0_field( - x: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { +pub(crate) fn big_sig0_field(x: &[impl Into + Clone]) -> Vec { xor(&rotr::(x, 2), &rotr::(x, 13), &rotr::(x, 22)) } /// Big sigma_1 function from SHA256 -pub fn big_sig1(x: u32) -> u32 { +pub fn big_sig1(x: C::Word) -> C::Word { x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25) } /// Computes BigSigma1(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn big_sig1_field( - x: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { +pub(crate) fn big_sig1_field(x: &[impl Into + Clone]) -> Vec { xor(&rotr::(x, 6), &rotr::(x, 11), &rotr::(x, 25)) } /// Small sigma_0 function from SHA256 -pub fn small_sig0(x: u32) -> u32 { +pub fn small_sig0(x: C::Word) -> C::Word { x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) } /// Computes SmallSigma0(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn small_sig0_field( - x: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { +pub(crate) fn small_sig0_field(x: &[impl Into + Clone]) -> Vec { xor(&rotr::(x, 7), &rotr::(x, 18), &shr::(x, 3)) } /// Small sigma_1 function from SHA256 -pub fn small_sig1(x: u32) -> u32 { +pub fn small_sig1(x: C::Word) -> C::Word { x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) } /// Computes SmallSigma1(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn small_sig1_field( - x: &[impl Into + Clone; SHA256_WORD_BITS], -) -> [F; SHA256_WORD_BITS] { +pub(crate) fn small_sig1_field(x: &[impl Into + Clone]) -> Vec { xor(&rotr::(x, 17), &rotr::(x, 19), &shr::(x, 10)) } @@ -235,21 +215,26 @@ pub fn get_random_message(rng: &mut StdRng, len: usize) -> Vec { } /// Wrapper of `get_flag_pt` to get the flag pointer as an array -pub fn get_flag_pt_array(encoder: &Encoder, flag_idx: usize) -> [u32; N] { - encoder.get_flag_pt(flag_idx).try_into().unwrap() +pub fn get_flag_pt_array(encoder: &Encoder, flag_idx: usize) -> Vec { + encoder.get_flag_pt(flag_idx) } /// Constrain the addition of [SHA256_WORD_BITS] bit words in 16-bit limbs /// It takes in the terms some in bits some in 16-bit limbs, /// the expected sum in bits and the carries -pub fn constraint_word_addition( +pub fn constraint_word_addition( builder: &mut AB, - terms_bits: &[&[impl Into + Clone; SHA256_WORD_BITS]], - terms_limb: &[&[impl Into + Clone; SHA256_WORD_U16S]], - expected_sum: &[impl Into + Clone; SHA256_WORD_BITS], - carries: &[impl Into + Clone; SHA256_WORD_U16S], + terms_bits: &[&[impl Into + Clone]], + terms_limb: &[&[impl Into + Clone]], + expected_sum: &[impl Into + Clone], + carries: &[impl Into + Clone], ) { - for i in 0..SHA256_WORD_U16S { + debug_assert!(terms_bits.iter().all(|x| x.len() == C::WORD_BITS)); + debug_assert!(terms_limb.iter().all(|x| x.len() == C::WORD_U16S)); + assert_eq!(expected_sum.len(), C::WORD_BITS); + assert_eq!(carries.len(), C::WORD_U16S); + + for i in 0..C::WORD_U16S { let mut limb_sum = if i == 0 { AB::Expr::ZERO } else { From 2844e8851d5f83377a972b8a31bd6097e5b7e8c5 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 10 Feb 2025 16:08:36 -0500 Subject: [PATCH 3/7] Fix typo bug --- crates/circuits/sha256-air/src/trace.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/circuits/sha256-air/src/trace.rs b/crates/circuits/sha256-air/src/trace.rs index 788c8eb22d..5494571be6 100644 --- a/crates/circuits/sha256-air/src/trace.rs +++ b/crates/circuits/sha256-air/src/trace.rs @@ -107,8 +107,7 @@ impl> ShaAir { *cols.flags.local_block_idx = F::from_canonical_u32(local_block_idx); // W_idx = M_idx - // TODO: fix this. should be smtg like `if i < C::BLOCK_WORDS` - if i < C::ROWS_PER_BLOCK / C::ROUNDS_PER_ROW { + if i < C::BLOCK_WORDS / C::ROUNDS_PER_ROW { for j in 0..C::ROUNDS_PER_ROW { cols.message_schedule .w From 4f1038a340076445fcec4aed10880085c8f7e51d Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 10 Feb 2025 17:10:28 -0500 Subject: [PATCH 4/7] Added sha512 support to the air --- Cargo.lock | 2 +- crates/circuits/sha-macros/src/lib.rs | 8 +- crates/circuits/sha256-air/src/air.rs | 93 +++++++++++++---------- crates/circuits/sha256-air/src/columns.rs | 2 +- crates/circuits/sha256-air/src/config.rs | 26 +++++-- crates/circuits/sha256-air/src/tests.rs | 8 +- crates/circuits/sha256-air/src/trace.rs | 87 +++++++++++---------- crates/circuits/sha256-air/src/utils.rs | 80 +++++++++++++------ 8 files changed, 187 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19b446e756..530809a0cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4114,7 +4114,7 @@ dependencies = [ "openvm-sha256-air", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.98", ] [[package]] diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs index 19505448df..9fc75ea264 100644 --- a/crates/circuits/sha-macros/src/lib.rs +++ b/crates/circuits/sha-macros/src/lib.rs @@ -172,12 +172,12 @@ fn make_struct(struct_info: StructInfo) -> proc_macro2::TokenStream { fn make_from_mut(struct_info: StructInfo) -> Result { let StructInfo { name, - vis, + vis: _, generic_type, - field_infos, + field_infos: _, fields, - from_args, - derive_clone, + from_args: _, + derive_clone: _, } = struct_info; let fields = match fields { diff --git a/crates/circuits/sha256-air/src/air.rs b/crates/circuits/sha256-air/src/air.rs index 970185d01b..49946f6f9e 100644 --- a/crates/circuits/sha256-air/src/air.rs +++ b/crates/circuits/sha256-air/src/air.rs @@ -37,7 +37,7 @@ impl> ShaAir { pub fn new(bitwise_lookup_bus: BitwiseOperationLookupBus, self_bus_idx: BusIndex) -> Self { Self { bitwise_lookup_bus, - row_idx_encoder: Encoder::new(18, 2, false), + row_idx_encoder: Encoder::new(C::ROWS_PER_BLOCK + 1, 2, false), // + 1 for dummy (padding) rows bus: PermutationCheckBus::new(self_bus_idx), _phantom: PhantomData, } @@ -91,29 +91,35 @@ impl> ShaAir { self.row_idx_encoder .eval(builder, local_cols.flags.row_idx.to_slice().unwrap()); - builder.assert_one( - self.row_idx_encoder - .contains_flag_range::(local_cols.flags.row_idx.to_slice().unwrap(), 0..=17), - ); + builder.assert_one(self.row_idx_encoder.contains_flag_range::( + local_cols.flags.row_idx.to_slice().unwrap(), + 0..=C::ROWS_PER_BLOCK, + )); builder.assert_eq( self.row_idx_encoder .contains_flag_range::(local_cols.flags.row_idx.to_slice().unwrap(), 0..=3), *flags.is_first_4_rows, ); builder.assert_eq( - self.row_idx_encoder - .contains_flag_range::(local_cols.flags.row_idx.to_slice().unwrap(), 0..=15), + self.row_idx_encoder.contains_flag_range::( + local_cols.flags.row_idx.to_slice().unwrap(), + 0..=C::ROUND_ROWS - 1, + ), *flags.is_round_row, ); builder.assert_eq( - self.row_idx_encoder - .contains_flag::(local_cols.flags.row_idx.to_slice().unwrap(), &[16]), + self.row_idx_encoder.contains_flag::( + local_cols.flags.row_idx.to_slice().unwrap(), + &[C::ROUND_ROWS], + ), *flags.is_digest_row, ); - // If padding row we want the row_idx to be 17 + // If padding row we want the row_idx to be C::ROWS_PER_BLOCK builder.assert_eq( - self.row_idx_encoder - .contains_flag::(local_cols.flags.row_idx.to_slice().unwrap(), &[17]), + self.row_idx_encoder.contains_flag::( + local_cols.flags.row_idx.to_slice().unwrap(), + &[C::ROWS_PER_BLOCK], + ), flags.is_padding_row(), ); @@ -130,14 +136,14 @@ impl> ShaAir { /// Implements constraints for a digest row that ensure proper state transitions between blocks /// This validates that: /// The work variables are correctly initialized for the next message block - /// For the last message block, the initial state matches SHA256_H constants + /// For the last message block, the initial state matches SHA_H constants fn eval_digest_row( &self, builder: &mut AB, local: ShaRoundColsRef, next: ShaDigestColsRef, ) { - // Check that if this is the last row of a message or an inpadding row, the hash should be the [SHA256_H] + // Check that if this is the last row of a message or an inpadding row, the hash should be the [SHA_H] for i in 0..C::ROUNDS_PER_ROW { let a = next.hash.a.row(i).mapv(|x| x.into()).to_vec(); let e = next.hash.e.row(i).mapv(|x| x.into()).to_vec(); @@ -146,7 +152,7 @@ impl> ShaAir { let a_limb = compose::(&a[j * 16..(j + 1) * 16], 1); let e_limb = compose::(&e[j * 16..(j + 1) * 16], 1); - // If it is a padding row or the last row of a message, the `hash` should be the [SHA256_H] + // If it is a padding row or the last row of a message, the `hash` should be the [SHA_H] builder .when( next.flags.is_padding_row() @@ -278,24 +284,24 @@ impl> ShaAir { // Constrain how much the row index changes by // round->round: 1 // round->digest: 1 - // digest->round: -16 // TODO: sha512 + // digest->round: -C::ROUND_ROWS // digest->padding: 1 // padding->padding: 0 // Other transitions are not allowed by the above constraints let delta = *local_cols.flags.is_round_row * AB::Expr::ONE + *local_cols.flags.is_digest_row * *next_cols.flags.is_round_row - * AB::Expr::from_canonical_u32(16) + * AB::Expr::from_canonical_usize(C::ROUND_ROWS) * AB::Expr::NEG_ONE + *local_cols.flags.is_digest_row * next_is_padding_row.clone() * AB::Expr::ONE; let local_row_idx = self.row_idx_encoder.flag_with_val::( local_cols.flags.row_idx.to_slice().unwrap(), - &(0..18).map(|i| (i, i)).collect::>(), + &(0..=C::ROWS_PER_BLOCK).map(|i| (i, i)).collect::>(), ); let next_row_idx = self.row_idx_encoder.flag_with_val::( next_cols.flags.row_idx.to_slice().unwrap(), - &(0..18).map(|i| (i, i)).collect::>(), + &(0..=C::ROWS_PER_BLOCK).map(|i| (i, i)).collect::>(), ); builder @@ -458,20 +464,22 @@ impl> ShaAir { } // Constrain intermed for `next` row - // We will only constrain intermed_12 for rows [3, 14], and let it be unconstrained for other rows + // We will only constrain intermed_12 for rows [3, 14], and let it unconstrained for other rows // Other rows should put the needed value in intermed_12 to make the below summation constraint hold - let is_row_3_14 = self - .row_idx_encoder - .contains_flag_range::(next.flags.row_idx.to_slice().unwrap(), 3..=14); - // We will only constrain intermed_8 for rows [2, 13], and let it unconstrained for other rows - let is_row_2_13 = self - .row_idx_encoder - .contains_flag_range::(next.flags.row_idx.to_slice().unwrap(), 2..=13); + let is_row_intermed_12 = self.row_idx_encoder.contains_flag_range::( + next.flags.row_idx.to_slice().unwrap(), + 3..=C::ROUND_ROWS - 2, + ); + // We will only constrain intermed_8 for rows [2, C::ROUND_ROWS - 2], and let it unconstrained for other rows + let is_row_intermed_8 = self.row_idx_encoder.contains_flag_range::( + next.flags.row_idx.to_slice().unwrap(), + 2..=C::ROUND_ROWS - 3, + ); for i in 0..C::ROUNDS_PER_ROW { // w_idx let w_idx = w.row(i).mapv(|x| x.into()).to_vec(); // sig_0(w_{idx+1}) - let sig_w = small_sig0_field::(w.row(i + 1).as_slice().unwrap()); + let sig_w = small_sig0_field::(w.row(i + 1).as_slice().unwrap()); for j in 0..C::WORD_U16S { let w_idx_limb = compose::(&w_idx[j * 16..(j + 1) * 16], 1); let sig_w_limb = compose::(&sig_w[j * 16..(j + 1) * 16], 1); @@ -483,12 +491,12 @@ impl> ShaAir { w_idx_limb + sig_w_limb, ); - builder.when(is_row_2_13.clone()).assert_eq( + builder.when(is_row_intermed_8.clone()).assert_eq( next.schedule_helper.intermed_8[[i, j]], local.schedule_helper.intermed_4[[i, j]], ); - builder.when(is_row_3_14.clone()).assert_eq( + builder.when(is_row_intermed_12.clone()).assert_eq( next.schedule_helper.intermed_12[[i, j]], local.schedule_helper.intermed_8[[i, j]], ); @@ -524,7 +532,7 @@ impl> ShaAir { constraint_word_addition::<_, C>( // Note: here we can't do a conditional check because the degree of sum is already 3 &mut builder.when_transition(), - &[&small_sig1_field::( + &[&small_sig1_field::( w.row(i + 2).as_slice().unwrap(), )], &[&w_7, intermed_16.as_slice().unwrap()], @@ -533,13 +541,13 @@ impl> ShaAir { ); for j in 0..C::WORD_U16S { - // When on rows 4..16 message schedule carries should be 0 or 1 - let is_row_4_15 = *next.flags.is_round_row - *next.flags.is_first_4_rows; + // When on rows 4..C::ROUND_ROWS message schedule carries should be 0 or 1 + let is_row_4_or_more = *next.flags.is_round_row - *next.flags.is_first_4_rows; builder - .when(is_row_4_15.clone()) + .when(is_row_4_or_more.clone()) .assert_bool(next.message_schedule.carry_or_buffer[[i, j * 2]]); builder - .when(is_row_4_15) + .when(is_row_4_or_more) .assert_bool(next.message_schedule.carry_or_buffer[[i, j * 2 + 1]]); } // Constrain w being composed of bits @@ -551,7 +559,7 @@ impl> ShaAir { } } - /// Constrain the work vars on `next` row according to the sha256 documentation + /// Constrain the work vars on `next` row according to the sha documentation /// Refer to [https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf] fn eval_work_vars<'a, AB: InteractionBuilder>( &self, @@ -588,11 +596,12 @@ impl> ShaAir { ) * *next.flags.is_round_row }) .collect::>(); + let k_limbs = (0..C::WORD_U16S) .map(|j| { self.row_idx_encoder.flag_with_val::( next.flags.row_idx.to_slice().unwrap(), - &(0..16) + &(0..C::ROUND_ROWS) .map(|rw_idx| { ( rw_idx, @@ -613,13 +622,13 @@ impl> ShaAir { builder, &[ e.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `h` - &big_sig1_field::(e.row(i + 3).as_slice().unwrap()), // sig_1 of previous `e` + &big_sig1_field::(e.row(i + 3).as_slice().unwrap()), // sig_1 of previous `e` &ch_field::( e.row(i + 3).as_slice().unwrap(), e.row(i + 2).as_slice().unwrap(), e.row(i + 1).as_slice().unwrap(), ), // Ch of previous `e`, `f`, `g` - &big_sig0_field::(a.row(i + 3).as_slice().unwrap()), // sig_0 of previous `a` + &big_sig0_field::(a.row(i + 3).as_slice().unwrap()), // sig_0 of previous `a` &maj_field::( a.row(i + 3).as_slice().unwrap(), a.row(i + 2).as_slice().unwrap(), @@ -637,9 +646,9 @@ impl> ShaAir { constraint_word_addition::<_, C>( builder, &[ - &a.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `d` - &e.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `h` - &big_sig1_field::(e.row(i + 3).as_slice().unwrap()), // sig_1 of previous `e` + a.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `d` + e.row(i).mapv(|x| x.into()).as_slice().unwrap(), // previous `h` + &big_sig1_field::(e.row(i + 3).as_slice().unwrap()), // sig_1 of previous `e` &ch_field::( e.row(i + 3).as_slice().unwrap(), e.row(i + 2).as_slice().unwrap(), diff --git a/crates/circuits/sha256-air/src/columns.rs b/crates/circuits/sha256-air/src/columns.rs index 43916e8afc..cee0249e96 100644 --- a/crates/circuits/sha256-air/src/columns.rs +++ b/crates/circuits/sha256-air/src/columns.rs @@ -82,7 +82,7 @@ pub struct ShaMessageScheduleCols< /// The message schedule words as C::WORD_BITS-bit integers /// The first 16 rows will be the message data pub w: [[T; WORD_BITS]; ROUNDS_PER_ROW], - /// Will be message schedule carries for rows 4..16 and a buffer for rows 0..4 to be used freely by wrapper chips + /// 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 /// Note: carries are 2 bit numbers represented using 2 cells as individual bits pub carry_or_buffer: [[T; WORD_U8S]; ROUNDS_PER_ROW], } diff --git a/crates/circuits/sha256-air/src/config.rs b/crates/circuits/sha256-air/src/config.rs index 93c2842ef4..efd7cca8f7 100644 --- a/crates/circuits/sha256-air/src/config.rs +++ b/crates/circuits/sha256-air/src/config.rs @@ -32,6 +32,10 @@ pub trait ShaConfig: Send + Sync + Clone { const ROWS_PER_BLOCK: usize; /// Number of rounds per row. Must divide Self::ROUNDS_PER_BLOCK const ROUNDS_PER_ROW: usize; + /// Number of rows used for the sha rounds + const ROUND_ROWS: usize = Self::ROUNDS_PER_BLOCK / Self::ROUNDS_PER_ROW; + /// Number of rows used for the message + const MESSAGE_ROWS: usize = Self::BLOCK_WORDS / Self::ROUNDS_PER_ROW; /// Number of rounds per row minus one (needed for one of the column structs) const ROUNDS_PER_ROW_MINUS_ONE: usize = Self::ROUNDS_PER_ROW - 1; /// Number of rounds per block. Must be a multiple of Self::ROUNDS_PER_ROW @@ -121,6 +125,7 @@ pub const SHA256_INVALID_CARRY_E: [[u32; Sha256Config::WORD_U16S]; Sha256Config: [719953922, 1888246508], [194580482, 1075725211], ]; + /// SHA256 constant K's pub const SHA256_K: [u32; 64] = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -163,7 +168,7 @@ impl ShaConfig for Sha512Config { /// Number of words in a SHA512 block const BLOCK_WORDS: usize = 16; /// Number of rows per block - const ROWS_PER_BLOCK: usize = 21; // SHA-512 has 80 rounds, so needs more rows + const ROWS_PER_BLOCK: usize = 21; /// Number of rounds per row const ROUNDS_PER_ROW: usize = 4; /// Number of rounds per block @@ -171,17 +176,26 @@ impl ShaConfig for Sha512Config { /// Number of words in a SHA512 hash const HASH_WORDS: usize = 8; /// Number of vars needed to encode the row index with [Encoder] - const ROW_VAR_CNT: usize = 5; + const ROW_VAR_CNT: usize = 6; } -// TODO: fill in these constants - /// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows /// To optimize the trace generation of invalid rows, we have those values precomputed here pub(crate) const SHA512_INVALID_CARRY_A: [[u32; Sha512Config::WORD_U16S]; - Sha512Config::ROUNDS_PER_ROW] = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]; + Sha512Config::ROUNDS_PER_ROW] = [ + [55971842, 827997017, 993005918, 512731953], + [227512322, 1697529235, 1936430385, 940122990], + [1939875843, 1173318562, 826201586, 1513494849], + [891955202, 1732283693, 1736658755, 223514501], +]; + pub(crate) const SHA512_INVALID_CARRY_E: [[u32; Sha512Config::WORD_U16S]; - Sha512Config::ROUNDS_PER_ROW] = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]; + Sha512Config::ROUNDS_PER_ROW] = [ + [1384427522, 1509509767, 153131516, 102514978], + [1527552003, 1041677071, 837289497, 843522538], + [775188482, 1620184630, 744892564, 892058728], + [1801267202, 1393118048, 1846108940, 830635531], +]; /// SHA512 constant K's pub const SHA512_K: [u64; 80] = [ diff --git a/crates/circuits/sha256-air/src/tests.rs b/crates/circuits/sha256-air/src/tests.rs index 669ab2a8bb..4c567628de 100644 --- a/crates/circuits/sha256-air/src/tests.rs +++ b/crates/circuits/sha256-air/src/tests.rs @@ -18,9 +18,8 @@ use openvm_stark_backend::{ rap::{get_air_name, BaseAirWithPublicValues, PartitionedBaseAir}, AirRef, Chip, ChipUsageGetter, }; -use openvm_stark_sdk::{p3_baby_bear::BabyBear, utils::create_seeded_rng}; +use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; -use sha2::Sha256; use crate::{ compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, ShaFlagsColsRef, @@ -128,6 +127,11 @@ fn rand_sha256_test() { rand_sha_test::(); } +#[test] +fn rand_sha512_test() { + rand_sha_test::(); +} + // A wrapper Chip to test that the final_hash is properly constrained. // This chip implements a malicious trace gen that violates the final_hash constraints. pub struct ShaTestBadFinalHashChip> { diff --git a/crates/circuits/sha256-air/src/trace.rs b/crates/circuits/sha256-air/src/trace.rs index 5494571be6..01cbf3a274 100644 --- a/crates/circuits/sha256-air/src/trace.rs +++ b/crates/circuits/sha256-air/src/trace.rs @@ -1,6 +1,5 @@ -use std::{array, borrow::BorrowMut, ops::Range}; +use std::ops::Range; -use ndarray::{concatenate, ArrayViewMut1}; use openvm_circuit_primitives::{ bitwise_op_lookup::SharedBitwiseOperationLookupChip, utils::next_power_of_two_or_zero, }; @@ -15,9 +14,9 @@ use super::{ small_sig0_field, small_sig1_field, ShaRoundColsRefMut, }; use crate::{ - big_sig0, big_sig1, ch, limbs_into_u32, limbs_into_word, maj, small_sig0, small_sig1, - u32_into_bits, word_into_bits, word_into_u16_limbs, word_into_u8_limbs, ShaConfig, - ShaDigestColsRefMut, ShaPrecomputedValues, ShaRoundColsRef, WrappingAdd, + big_sig0, big_sig1, ch, limbs_into_word, maj, small_sig0, small_sig1, word_into_bits, + word_into_u16_limbs, word_into_u8_limbs, ShaConfig, ShaDigestColsRefMut, ShaPrecomputedValues, + ShaRoundColsRef, WrappingAdd, }; /// The trace generation of SHA256 should be done in two passes. @@ -46,11 +45,11 @@ impl> ShaAir { new_hash.to_vec() } - /// This function takes a 512-bit chunk of the input message (padding not handled), the previous hash, + /// This function takes a (C::WORD_BITS * C::BLOCK_WORDS)-bit chunk of the input message (padding not handled), the previous hash, /// a flag indicating if it's the last block, the global block index, the local block index, /// and the buffer values that will be put in rows 0..4. /// Will populate the given `trace` with the trace of the block, where the width of the trace is `trace_width` - /// and the starting column for the `Sha256Air` is `trace_start_col`. + /// and the starting column for the `ShaAir` is `trace_start_col`. /// **Note**: this function only generates some of the required trace. Another pass is required, refer to [`Self::generate_missing_cells`] for details. #[allow(clippy::too_many_arguments)] pub fn generate_block_trace( @@ -64,13 +63,14 @@ impl> ShaAir { is_last_block: bool, global_block_idx: u32, local_block_idx: u32, - buffer_vals: &[&[F]; 4], + buffer_vals: Vec<&[F]>, ) { - debug_assert!(input.len() == C::BLOCK_WORDS); - debug_assert!(prev_hash.len() == C::HASH_WORDS); - debug_assert!(buffer_vals.iter().all(|x| x.len() == C::BUFFER_SIZE)); #[cfg(debug_assertions)] { + assert!(input.len() == C::BLOCK_WORDS); + assert!(prev_hash.len() == C::HASH_WORDS); + assert!(buffer_vals.len() == C::MESSAGE_ROWS); + assert!(buffer_vals.iter().all(|x| x.len() == C::BUFFER_SIZE)); assert!(trace.len() == trace_width * C::ROWS_PER_BLOCK); assert!(trace_start_col + C::WIDTH <= trace_width); assert!(self.bitwise_lookup_bus == bitwise_lookup_chip.bus()); @@ -83,9 +83,8 @@ impl> ShaAir { message_schedule[..input.len()].copy_from_slice(input); let mut work_vars = prev_hash.to_vec(); for (i, row) in trace.chunks_exact_mut(trace_width).enumerate() { - // TODO: sha512 - // doing the 64 rounds in 16 rows - if i < 16 { + // do the rounds + if i < C::ROUND_ROWS { let mut cols: ShaRoundColsRefMut = ShaRoundColsRefMut::from::( &mut row[get_range(trace_start_col, C::ROUND_WIDTH)], ); @@ -107,7 +106,7 @@ impl> ShaAir { *cols.flags.local_block_idx = F::from_canonical_u32(local_block_idx); // W_idx = M_idx - if i < C::BLOCK_WORDS / C::ROUNDS_PER_ROW { + if i < C::MESSAGE_ROWS { for j in 0..C::ROUNDS_PER_ROW { cols.message_schedule .w @@ -186,15 +185,14 @@ impl> ShaAir { big_sig1::(work_vars[4]), ch::(work_vars[4], work_vars[5], work_vars[6]), C::get_k()[i * C::ROUNDS_PER_ROW + j], - limbs_into_u32( + limbs_into_word::( cols.message_schedule .w .row(j) .map(|f| f.as_canonical_u32()) .as_slice() .unwrap(), - ) - .into(), + ), ]; let t1_sum: C::Word = t1 .iter() @@ -329,7 +327,7 @@ impl> ShaAir { .row_idx .iter_mut() .zip( - get_flag_pt_array(&self.row_idx_encoder, 16) + get_flag_pt_array(&self.row_idx_encoder, C::ROUND_ROWS) .into_iter() .map(F::from_canonical_u32), ) @@ -358,14 +356,16 @@ impl> ShaAir { word_into_u8_limbs::(final_hash[i]) .into_iter() .map(F::from_canonical_u32) + .collect::>() })) .for_each(|(x, y)| *x = y); cols.prev_hash .iter_mut() - .zip(prev_hash.into_iter().flat_map(|f| { + .zip(prev_hash.iter().flat_map(|f| { word_into_u16_limbs::(*f) .into_iter() .map(F::from_canonical_u32) + .collect::>() })) .for_each(|(x, y)| *x = y); @@ -379,9 +379,11 @@ impl> ShaAir { .rows_mut() .into_iter() .map(|f| { - limbs_into_u32(f.map(|x| x.as_canonical_u32()).as_slice().unwrap()) + limbs_into_word::( + f.map(|x| x.as_canonical_u32()).as_slice().unwrap(), + ) }) - .map(u32_into_bits::) + .map(word_into_bits::) .collect() } .into_iter() @@ -494,7 +496,7 @@ impl> ShaAir { .row_idx .iter_mut() .zip( - get_flag_pt_array(&self.row_idx_encoder, 17) + get_flag_pt_array(&self.row_idx_encoder, C::ROWS_PER_BLOCK) .into_iter() .map(F::from_canonical_u32), ) @@ -554,9 +556,9 @@ impl> ShaAir { /// The following functions do the calculations in native field since they will be called on padding rows /// which can overflow and we need to make sure it matches the AIR constraints /// Puts the correct carrys in the `next_row`, the resulting carrys can be out of bound - fn generate_carry_ae<'a, 'b, F: PrimeField32>( - local_cols: ShaRoundColsRef<'a, F>, - next_cols: &mut ShaRoundColsRefMut<'b, F>, + pub fn generate_carry_ae( + local_cols: ShaRoundColsRef, + next_cols: &mut ShaRoundColsRefMut, ) { let a = [ local_cols @@ -580,7 +582,7 @@ impl> ShaAir { .concat(); for i in 0..C::ROUNDS_PER_ROW { let cur_a = a[i + 4]; - let sig_a = big_sig0_field::(a[i + 3].as_slice().unwrap()); + let sig_a = big_sig0_field::(a[i + 3].as_slice().unwrap()); let maj_abc = maj_field::( a[i + 3].as_slice().unwrap(), a[i + 2].as_slice().unwrap(), @@ -588,7 +590,7 @@ impl> ShaAir { ); let d = a[i]; let cur_e = e[i + 4]; - let sig_e = big_sig1_field::(e[i + 3].as_slice().unwrap()); + let sig_e = big_sig1_field::(e[i + 3].as_slice().unwrap()); let ch_efg = ch_field::( e[i + 3].as_slice().unwrap(), e[i + 2].as_slice().unwrap(), @@ -634,9 +636,9 @@ impl> ShaAir { } /// Puts the correct intermed_4 in the `next_row` - fn generate_intermed_4<'a, 'b, F: PrimeField32>( - local_cols: ShaRoundColsRef<'a, F>, - next_cols: &mut ShaRoundColsRefMut<'b, F>, + fn generate_intermed_4( + local_cols: ShaRoundColsRef, + next_cols: &mut ShaRoundColsRefMut, ) { let w = [ local_cols @@ -662,7 +664,7 @@ impl> ShaAir { }) .collect(); for i in 0..C::ROUNDS_PER_ROW { - let sig_w = small_sig0_field::(w[i + 1].as_slice().unwrap()); + let sig_w = small_sig0_field::(w[i + 1].as_slice().unwrap()); let sig_w_limbs: Vec = (0..C::WORD_U16S) .map(|j| compose::(&sig_w[j * 16..(j + 1) * 16], 1)) .collect(); @@ -673,9 +675,9 @@ impl> ShaAir { } /// Puts the needed intermed_12 in the `local_row` - fn generate_intermed_12<'a, 'b, F: PrimeField32>( - local_cols: &mut ShaRoundColsRefMut<'a, F>, - next_cols: ShaRoundColsRef<'b, F>, + fn generate_intermed_12( + local_cols: &mut ShaRoundColsRefMut, + next_cols: ShaRoundColsRef, ) { let w = [ local_cols @@ -705,7 +707,8 @@ impl> ShaAir { let sig_w_2: Vec = (0..C::WORD_U16S) .map(|j| { compose::( - &small_sig1_field::(w[i + 2].as_slice().unwrap())[j * 16..(j + 1) * 16], + &small_sig1_field::(w[i + 2].as_slice().unwrap()) + [j * 16..(j + 1) * 16], 1, ) }) @@ -745,16 +748,19 @@ pub fn generate_trace as BaseAir>::width(sub_air); let mut values = F::zero_vec(height * width); struct BlockContext { - prev_hash: Vec, // HASH_WORDS + prev_hash: Vec, // len is C::HASH_WORDS local_block_idx: u32, global_block_idx: u32, - input: Vec, // BLOCK_U8S + input: Vec, // len is C::BLOCK_U8S is_last_block: bool, } let mut block_ctx: Vec> = Vec::with_capacity(records.len()); @@ -801,7 +807,7 @@ pub fn generate_trace>(); let empty_buffer = vec![F::ZERO; C::BUFFER_SIZE]; - let buffer_vals = [empty_buffer.as_slice(); 4]; + let buffer_vals = vec![empty_buffer.as_slice(); C::MESSAGE_ROWS]; sub_air.generate_block_trace( block, width, @@ -812,7 +818,7 @@ pub fn generate_trace = ShaRoundColsRefMut::from::(row); sub_air.generate_default_row(cols); }); + // second pass: non-padding rows values[width..] .par_chunks_mut(width * C::ROWS_PER_BLOCK) diff --git a/crates/circuits/sha256-air/src/utils.rs b/crates/circuits/sha256-air/src/utils.rs index 72dac93474..756fd7ca2e 100644 --- a/crates/circuits/sha256-air/src/utils.rs +++ b/crates/circuits/sha256-air/src/utils.rs @@ -5,7 +5,10 @@ use openvm_circuit_primitives::{ encoder::Encoder, utils::{not, select}, }; -use openvm_stark_backend::{p3_air::AirBuilder, p3_field::FieldAlgebra}; +use openvm_stark_backend::{ + p3_air::AirBuilder, + p3_field::{FieldAlgebra, PrimeField32}, +}; use rand::{rngs::StdRng, Rng}; use crate::{RotateRight, ShaConfig}; @@ -46,15 +49,6 @@ pub fn u32_into_bits(num: u32) -> Vec { .collect() } -// TODO: delete -/* -/// Convert a u32 into a list of limbs in little endian -pub fn u32_into_limbs(num: u32) -> [u32; NUM_LIMBS] { - let limb_bits = 32 / NUM_LIMBS; - array::from_fn(|i| (num >> (limb_bits * i)) & ((1 << limb_bits) - 1)) -} -*/ - /// Convert a list of limbs in little endian into a Word pub fn limbs_into_word(limbs: &[u32]) -> C::Word { let limb_bits = C::WORD_BITS / limbs.len(); @@ -165,46 +159,86 @@ pub(crate) fn maj_field( /// Big sigma_0 function from SHA256 pub fn big_sig0(x: C::Word) -> C::Word { - x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22) + if C::WORD_BITS == 32 { + x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22) + } else { + x.rotate_right(28) ^ x.rotate_right(34) ^ x.rotate_right(39) + } } -/// Computes BigSigma0(x), where x is a [SHA256_WORD_BITS] bit number in little-endian +/// Computes BigSigma0(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn big_sig0_field(x: &[impl Into + Clone]) -> Vec { - xor(&rotr::(x, 2), &rotr::(x, 13), &rotr::(x, 22)) +pub(crate) fn big_sig0_field( + x: &[impl Into + Clone], +) -> Vec { + if C::WORD_BITS == 32 { + xor(&rotr::(x, 2), &rotr::(x, 13), &rotr::(x, 22)) + } else { + xor(&rotr::(x, 28), &rotr::(x, 34), &rotr::(x, 39)) + } } /// Big sigma_1 function from SHA256 pub fn big_sig1(x: C::Word) -> C::Word { - x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25) + if C::WORD_BITS == 32 { + x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25) + } else { + x.rotate_right(14) ^ x.rotate_right(18) ^ x.rotate_right(41) + } } /// Computes BigSigma1(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn big_sig1_field(x: &[impl Into + Clone]) -> Vec { - xor(&rotr::(x, 6), &rotr::(x, 11), &rotr::(x, 25)) +pub(crate) fn big_sig1_field( + x: &[impl Into + Clone], +) -> Vec { + if C::WORD_BITS == 32 { + xor(&rotr::(x, 6), &rotr::(x, 11), &rotr::(x, 25)) + } else { + xor(&rotr::(x, 14), &rotr::(x, 18), &rotr::(x, 41)) + } } /// Small sigma_0 function from SHA256 pub fn small_sig0(x: C::Word) -> C::Word { - x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) + if C::WORD_BITS == 32 { + x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) + } else { + x.rotate_right(1) ^ x.rotate_right(8) ^ (x >> 7) + } } /// Computes SmallSigma0(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn small_sig0_field(x: &[impl Into + Clone]) -> Vec { - xor(&rotr::(x, 7), &rotr::(x, 18), &shr::(x, 3)) +pub(crate) fn small_sig0_field( + x: &[impl Into + Clone], +) -> Vec { + if C::WORD_BITS == 32 { + xor(&rotr::(x, 7), &rotr::(x, 18), &shr::(x, 3)) + } else { + xor(&rotr::(x, 1), &rotr::(x, 8), &shr::(x, 7)) + } } /// Small sigma_1 function from SHA256 pub fn small_sig1(x: C::Word) -> C::Word { - x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) + if C::WORD_BITS == 32 { + x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) + } else { + x.rotate_right(19) ^ x.rotate_right(61) ^ (x >> 6) + } } /// Computes SmallSigma1(x), where x is a [SHA256_WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn small_sig1_field(x: &[impl Into + Clone]) -> Vec { - xor(&rotr::(x, 17), &rotr::(x, 19), &shr::(x, 10)) +pub(crate) fn small_sig1_field( + x: &[impl Into + Clone], +) -> Vec { + if C::WORD_BITS == 32 { + xor(&rotr::(x, 17), &rotr::(x, 19), &shr::(x, 10)) + } else { + xor(&rotr::(x, 19), &rotr::(x, 61), &shr::(x, 6)) + } } /// Generate a random message of a given length From 1f44957ab62396971dc05e863917b8121e9ac773 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Wed, 12 Feb 2025 12:04:25 -0500 Subject: [PATCH 5/7] Updated names --- .github/workflows/primitives.yml | 6 +-- Cargo.lock | 2 +- Cargo.toml | 2 +- .../{sha256-air => sha-air}/Cargo.toml | 2 +- .../{sha256-air => sha-air}/src/air.rs | 0 .../{sha256-air => sha-air}/src/columns.rs | 49 +++++-------------- .../{sha256-air => sha-air}/src/config.rs | 9 ++-- .../{sha256-air => sha-air}/src/lib.rs | 2 +- .../{sha256-air => sha-air}/src/tests.rs | 0 .../{sha256-air => sha-air}/src/trace.rs | 7 +-- .../{sha256-air => sha-air}/src/utils.rs | 26 +++++----- crates/circuits/sha-macros/Cargo.toml | 2 +- crates/circuits/sha-macros/tests/flags.rs | 2 +- crates/circuits/sha-macros/tests/nested.rs | 7 ++- crates/circuits/sha-macros/tests/simple.rs | 2 +- crates/circuits/sha-macros/tests/work-vars.rs | 2 +- extensions/sha256/circuit/Cargo.toml | 2 +- .../sha256/circuit/src/sha256_chip/air.rs | 4 +- .../sha256/circuit/src/sha256_chip/columns.rs | 2 +- .../sha256/circuit/src/sha256_chip/mod.rs | 2 +- .../sha256/circuit/src/sha256_chip/tests.rs | 2 +- .../sha256/circuit/src/sha256_chip/trace.rs | 2 +- 22 files changed, 53 insertions(+), 81 deletions(-) rename crates/circuits/{sha256-air => sha-air}/Cargo.toml (95%) rename crates/circuits/{sha256-air => sha-air}/src/air.rs (100%) rename crates/circuits/{sha256-air => sha-air}/src/columns.rs (65%) rename crates/circuits/{sha256-air => sha-air}/src/config.rs (97%) rename crates/circuits/{sha256-air => sha-air}/src/lib.rs (75%) rename crates/circuits/{sha256-air => sha-air}/src/tests.rs (100%) rename crates/circuits/{sha256-air => sha-air}/src/trace.rs (99%) rename crates/circuits/{sha256-air => sha-air}/src/utils.rs (91%) diff --git a/.github/workflows/primitives.yml b/.github/workflows/primitives.yml index d94e1c25e1..9d833fb91f 100644 --- a/.github/workflows/primitives.yml +++ b/.github/workflows/primitives.yml @@ -8,7 +8,7 @@ on: paths: - "crates/circuits/primitives/**" - "crates/circuits/poseidon2-air/**" - - "crates/circuits/sha256-air/**" + - "crates/circuits/sha-air/**" - "Cargo.toml" concurrency: @@ -45,7 +45,7 @@ jobs: run: | cargo nextest run --cargo-profile fast --features parallel - - name: Run tests for sha256-air - working-directory: crates/circuits/sha256-air + - name: Run tests for sha-air + working-directory: crates/circuits/sha-air run: | cargo nextest run --cargo-profile fast --features parallel diff --git a/Cargo.lock b/Cargo.lock index 530809a0cc..ccead2b311 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4142,7 +4142,7 @@ dependencies = [ "openvm-circuit-primitives-derive", "openvm-instructions", "openvm-rv32im-circuit", - "openvm-sha256-air", + "openvm-sha-air", "openvm-sha256-transpiler", "openvm-stark-backend", "openvm-stark-sdk", diff --git a/Cargo.toml b/Cargo.toml index f384bb3615..7bee31cc5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,7 +112,7 @@ openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", re openvm-sdk = { path = "crates/sdk", default-features = false } openvm-mod-circuit-builder = { path = "crates/circuits/mod-builder", default-features = false } openvm-poseidon2-air = { path = "crates/circuits/poseidon2-air", default-features = false } -openvm-sha256-air = { path = "crates/circuits/sha256-air", default-features = false } +openvm-sha-air = { path = "crates/circuits/sha-air", default-features = false } openvm-sha-macros = { path = "crates/circuits/sha-macros", default-features = false } openvm-circuit-primitives = { path = "crates/circuits/primitives", default-features = false } openvm-circuit-primitives-derive = { path = "crates/circuits/primitives/derive", default-features = false } diff --git a/crates/circuits/sha256-air/Cargo.toml b/crates/circuits/sha-air/Cargo.toml similarity index 95% rename from crates/circuits/sha256-air/Cargo.toml rename to crates/circuits/sha-air/Cargo.toml index 9a8c76e16d..21524930cd 100644 --- a/crates/circuits/sha256-air/Cargo.toml +++ b/crates/circuits/sha-air/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "openvm-sha256-air" +name = "openvm-sha-air" version.workspace = true authors.workspace = true edition.workspace = true diff --git a/crates/circuits/sha256-air/src/air.rs b/crates/circuits/sha-air/src/air.rs similarity index 100% rename from crates/circuits/sha256-air/src/air.rs rename to crates/circuits/sha-air/src/air.rs diff --git a/crates/circuits/sha256-air/src/columns.rs b/crates/circuits/sha-air/src/columns.rs similarity index 65% rename from crates/circuits/sha256-air/src/columns.rs rename to crates/circuits/sha-air/src/columns.rs index cee0249e96..ab63922d0f 100644 --- a/crates/circuits/sha256-air/src/columns.rs +++ b/crates/circuits/sha-air/src/columns.rs @@ -6,14 +6,11 @@ use openvm_stark_backend::p3_field::FieldAlgebra; use crate::ShaConfig; -/// In each SHA256 block: -/// - First 16 rows use Sha256RoundCols -/// - Final row uses Sha256DigestCols +/// In each SHA block: +/// - First C::ROUND_ROWS rows use ShaRoundCols +/// - Final row uses ShaDigestCols /// -/// Note that for soundness, we require that there is always a padding row after the last digest row in the trace. -/// Right now, this is true because the unpadded height is a multiple of 17, and thus not a power of 2. -/// -/// Sha256RoundCols and Sha256DigestCols share the same first 3 fields: +/// ShaRoundCols and ShaDigestCols share the same first 3 fields: /// - flags /// - work_vars/hash (same type, different name) /// - schedule_helper @@ -21,8 +18,6 @@ use crate::ShaConfig; /// This design allows for: /// 1. Common constraints to work on either struct type by accessing these shared fields /// 2. Specific constraints to use the appropriate struct, with flags helping to do conditional constraints -/// -/// Note that the `Sha256WorkVarsCols` field it is used for different purposes in the two structs. #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] pub struct ShaRoundCols< @@ -35,7 +30,6 @@ pub struct ShaRoundCols< const ROW_VAR_CNT: usize, > { pub flags: ShaFlagsCols, - /// Stores the current state of the working variables pub work_vars: ShaWorkVarsCols, pub schedule_helper: ShaMessageHelperCols, @@ -55,11 +49,7 @@ pub struct ShaDigestCols< const ROW_VAR_CNT: usize, > { pub flags: ShaFlagsCols, - /// Will serve as previous hash values for the next block. - /// - on non-last blocks, this is the final hash of the current block - /// - on last blocks, this is the initial state constants, SHA256_H. - /// The work variables constraints are applied on all rows, so `carry_a` and `carry_e` - /// must be filled in with dummy values to ensure these constraints hold. + /// Will serve as previous hash values for the next block pub hash: ShaWorkVarsCols, pub schedule_helper: ShaMessageHelperCols, @@ -79,11 +69,10 @@ pub struct ShaMessageScheduleCols< const ROUNDS_PER_ROW: usize, const WORD_U8S: usize, > { - /// The message schedule words as C::WORD_BITS-bit integers - /// The first 16 rows will be the message data + /// The message schedule words as 32-bit intergers pub w: [[T; WORD_BITS]; ROUNDS_PER_ROW], /// 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 - /// Note: carries are 2 bit numbers represented using 2 cells as individual bits + /// Note: carries are represented as 2 bit numbers pub carry_or_buffer: [[T; WORD_U8S]; ROUNDS_PER_ROW], } @@ -114,12 +103,10 @@ pub struct ShaMessageHelperCols< const ROUNDS_PER_ROW_MINUS_ONE: usize, > { /// The following are used to move data forward to constrain the message schedule additions - /// The value of `w` (message schedule word) from 3 rounds ago - /// In general, `w_i` means `w` from `i` rounds ago + /// The value of `w` from 3 rounds ago pub w_3: [[T; WORD_U16S]; ROUNDS_PER_ROW_MINUS_ONE], /// Here intermediate(i) = w_i + sig_0(w_{i+1}) /// Intermed_t represents the intermediate t rounds ago - /// This is needed to constrain the message schedule, since we can only constrain on two rows at a time pub intermed_4: [[T; WORD_U16S]; ROUNDS_PER_ROW], pub intermed_8: [[T; WORD_U16S]; ROUNDS_PER_ROW], pub intermed_12: [[T; WORD_U16S]; ROUNDS_PER_ROW], @@ -128,38 +115,27 @@ pub struct ShaMessageHelperCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] pub struct ShaFlagsCols { - /// A flag that indicates if the current row is among the first C::ROUND_ROWS rows of a block. pub is_round_row: T, - /// A flag that indicates if the current row is among the first 4 rows of a block. + /// A flag that indicates if the current row is among the first 4 rows of a block pub is_first_4_rows: T, - /// A flag that indicates if the current row is the last (17th) row of a block. pub is_digest_row: T, - // A flag that indicates if the current row is the last block of the message. - // This flag is only used in digest rows. pub is_last_block: T, /// We will encode the row index [0..17) using 5 cells //#[length(ROW_VAR_CNT)] pub row_idx: [T; ROW_VAR_CNT], - /// The index of the current block in the trace starting at 1. - /// Set to 0 on padding rows. + /// The global index of the current block pub global_block_idx: T, - /// The index of the current block in the current message starting at 0. - /// Resets after every message. - /// Set to 0 on padding rows. + /// Will store the index of the current block in the current message starting from 0 pub local_block_idx: T, } impl, const ROW_VAR_CNT: usize> ShaFlagsCols { - // This refers to the padding rows that are added to the air to make the trace length a power of 2. - // Not to be confused with the padding added to messages as part of the SHA hash function. pub fn is_not_padding_row(&self) -> O { self.is_round_row + self.is_digest_row } - // This refers to the padding rows that are added to the air to make the trace length a power of 2. - // Not to be confused with the padding added to messages as part of the SHA hash function. pub fn is_padding_row(&self) -> O where O: FieldAlgebra, @@ -168,14 +144,11 @@ impl, const ROW_VAR_CNT: usize> } } -// We need to implement this for the ColsRef type as well impl<'a, O, T: Copy + core::ops::Add> ShaFlagsColsRef<'a, T> { pub fn is_not_padding_row(&self) -> O { *self.is_round_row + *self.is_digest_row } - // This refers to the padding rows that are added to the air to make the trace length a power of 2. - // Not to be confused with the padding added to messages as part of the SHA hash function. pub fn is_padding_row(&self) -> O where O: FieldAlgebra, diff --git a/crates/circuits/sha256-air/src/config.rs b/crates/circuits/sha-air/src/config.rs similarity index 97% rename from crates/circuits/sha256-air/src/config.rs rename to crates/circuits/sha-air/src/config.rs index efd7cca8f7..919486d2c5 100644 --- a/crates/circuits/sha256-air/src/config.rs +++ b/crates/circuits/sha-air/src/config.rs @@ -81,6 +81,9 @@ pub trait ShaConfig: Send + Sync + Clone { }; } +/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows +/// To optimize the trace generation of invalid rows, we precompute those values. +/// This trait also stores the constants K and H for the given SHA config. pub trait ShaPrecomputedValues { // these should be appropirately sized for the config fn get_invalid_carry_a(round_num: usize) -> &'static [u32]; @@ -111,8 +114,6 @@ impl ShaConfig for Sha256Config { const ROW_VAR_CNT: usize = 5; } -/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows -/// To optimize the trace generation of invalid rows, we have those values precomputed here pub const SHA256_INVALID_CARRY_A: [[u32; Sha256Config::WORD_U16S]; Sha256Config::ROUNDS_PER_ROW] = [ [1230919683, 1162494304], [266373122, 1282901987], @@ -179,8 +180,6 @@ impl ShaConfig for Sha512Config { const ROW_VAR_CNT: usize = 6; } -/// We can notice that `carry_a`'s and `carry_e`'s are always the same on invalid rows -/// To optimize the trace generation of invalid rows, we have those values precomputed here pub(crate) const SHA512_INVALID_CARRY_A: [[u32; Sha512Config::WORD_U16S]; Sha512Config::ROUNDS_PER_ROW] = [ [55971842, 827997017, 993005918, 512731953], @@ -308,7 +307,7 @@ impl ShaPrecomputedValues for Sha512Config { } // Needed to avoid compile errors in utils.rs -// don't ask me why this doesn't inf loop +// not sure why this doesn't inf loop pub trait RotateRight { fn rotate_right(self, n: u32) -> Self; } diff --git a/crates/circuits/sha256-air/src/lib.rs b/crates/circuits/sha-air/src/lib.rs similarity index 75% rename from crates/circuits/sha256-air/src/lib.rs rename to crates/circuits/sha-air/src/lib.rs index f103ae8903..7c7d095938 100644 --- a/crates/circuits/sha256-air/src/lib.rs +++ b/crates/circuits/sha-air/src/lib.rs @@ -1,4 +1,4 @@ -//! Implementation of the SHA256 compression function without padding +//! Implementation of the SHA256/SHA512 compression function without padding //! This this AIR doesn't constrain any of the message padding mod air; diff --git a/crates/circuits/sha256-air/src/tests.rs b/crates/circuits/sha-air/src/tests.rs similarity index 100% rename from crates/circuits/sha256-air/src/tests.rs rename to crates/circuits/sha-air/src/tests.rs diff --git a/crates/circuits/sha256-air/src/trace.rs b/crates/circuits/sha-air/src/trace.rs similarity index 99% rename from crates/circuits/sha256-air/src/trace.rs rename to crates/circuits/sha-air/src/trace.rs index 01cbf3a274..4bdc291efc 100644 --- a/crates/circuits/sha256-air/src/trace.rs +++ b/crates/circuits/sha-air/src/trace.rs @@ -19,7 +19,7 @@ use crate::{ ShaRoundColsRef, WrappingAdd, }; -/// The trace generation of SHA256 should be done in two passes. +/// The trace generation of SHA should be done in two passes. /// The first pass should do `get_block_trace` for every block and generate the invalid rows through `get_default_row` /// The second pass should go through all the blocks and call `generate_missing_cells` impl> ShaAir { @@ -455,7 +455,7 @@ impl> ShaAir { /// This function should be called only after `generate_block_trace` was called for all blocks /// And [`Self::generate_default_row`] is called for all invalid rows /// Will populate the missing values of `trace`, where the width of the trace is `trace_width` - /// and the starting column for the `Sha256Air` is `trace_start_col`. + /// and the starting column for the `ShaAir` is `trace_start_col`. /// Note: `trace` needs to be the rows 1..C::ROWS_PER_BLOCK of a block and the first row of the next block pub fn generate_missing_cells( &self, @@ -748,11 +748,8 @@ pub fn generate_trace as BaseAir>::width(sub_air); let mut values = F::zero_vec(height * width); diff --git a/crates/circuits/sha256-air/src/utils.rs b/crates/circuits/sha-air/src/utils.rs similarity index 91% rename from crates/circuits/sha256-air/src/utils.rs rename to crates/circuits/sha-air/src/utils.rs index 756fd7ca2e..6a3d483833 100644 --- a/crates/circuits/sha256-air/src/utils.rs +++ b/crates/circuits/sha-air/src/utils.rs @@ -102,7 +102,7 @@ pub(crate) fn xor_bit( + (not::(x) * not::(y) * z) } -/// Computes x ^ y ^ z, where x, y, z are [SHA256_WORD_BITS] bit numbers +/// Computes x ^ y ^ z, where x, y, z are [C::WORD_BITS] bit numbers #[inline] pub(crate) fn xor( x: &[impl Into + Clone], @@ -114,13 +114,13 @@ pub(crate) fn xor( .collect() } -/// Choose function from SHA256 +/// Choose function from the SHA spec #[inline] pub fn ch(x: C::Word, y: C::Word, z: C::Word) -> C::Word { (x & y) ^ ((!x) & z) } -/// Computes Ch(x,y,z), where x, y, z are [SHA256_WORD_BITS] bit numbers +/// Computes Ch(x,y,z), where x, y, z are [C::WORD_BITS] bit numbers #[inline] pub(crate) fn ch_field( x: &[impl Into + Clone], @@ -132,12 +132,12 @@ pub(crate) fn ch_field( .collect() } -/// Majority function from SHA256 +/// Majority function from the SHA spec pub fn maj(x: C::Word, y: C::Word, z: C::Word) -> C::Word { (x & y) ^ (x & z) ^ (y & z) } -/// Computes Maj(x,y,z), where x, y, z are [SHA256_WORD_BITS] bit numbers +/// Computes Maj(x,y,z), where x, y, z are [C::WORD_BITS] bit numbers #[inline] pub(crate) fn maj_field( x: &[impl Into + Clone], @@ -157,7 +157,7 @@ pub(crate) fn maj_field( .collect() } -/// Big sigma_0 function from SHA256 +/// Big sigma_0 function from the SHA spec pub fn big_sig0(x: C::Word) -> C::Word { if C::WORD_BITS == 32 { x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22) @@ -178,7 +178,7 @@ pub(crate) fn big_sig0_field( } } -/// Big sigma_1 function from SHA256 +/// Big sigma_1 function from the SHA spec pub fn big_sig1(x: C::Word) -> C::Word { if C::WORD_BITS == 32 { x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25) @@ -187,7 +187,7 @@ pub fn big_sig1(x: C::Word) -> C::Word { } } -/// Computes BigSigma1(x), where x is a [SHA256_WORD_BITS] bit number in little-endian +/// Computes BigSigma1(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] pub(crate) fn big_sig1_field( x: &[impl Into + Clone], @@ -199,7 +199,7 @@ pub(crate) fn big_sig1_field( } } -/// Small sigma_0 function from SHA256 +/// Small sigma_0 function from the SHA spec pub fn small_sig0(x: C::Word) -> C::Word { if C::WORD_BITS == 32 { x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) @@ -208,7 +208,7 @@ pub fn small_sig0(x: C::Word) -> C::Word { } } -/// Computes SmallSigma0(x), where x is a [SHA256_WORD_BITS] bit number in little-endian +/// Computes SmallSigma0(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] pub(crate) fn small_sig0_field( x: &[impl Into + Clone], @@ -220,7 +220,7 @@ pub(crate) fn small_sig0_field( } } -/// Small sigma_1 function from SHA256 +/// Small sigma_1 function from the SHA spec pub fn small_sig1(x: C::Word) -> C::Word { if C::WORD_BITS == 32 { x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) @@ -229,7 +229,7 @@ pub fn small_sig1(x: C::Word) -> C::Word { } } -/// Computes SmallSigma1(x), where x is a [SHA256_WORD_BITS] bit number in little-endian +/// Computes SmallSigma1(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] pub(crate) fn small_sig1_field( x: &[impl Into + Clone], @@ -253,7 +253,7 @@ pub fn get_flag_pt_array(encoder: &Encoder, flag_idx: usize) -> Vec { encoder.get_flag_pt(flag_idx) } -/// Constrain the addition of [SHA256_WORD_BITS] bit words in 16-bit limbs +/// Constrain the addition of [C::WORD_BITS] bit words in 16-bit limbs /// It takes in the terms some in bits some in 16-bit limbs, /// the expected sum in bits and the carries pub fn constraint_word_addition( diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml index 7ed1af42d2..0930f05abe 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/sha-macros/Cargo.toml @@ -14,7 +14,7 @@ itertools = "0.14" proc-macro2 = "1.0" [dev-dependencies] -openvm-sha256-air = { workspace = true } +openvm-sha-air = { workspace = true } ndarray = "0.16" [lib] diff --git a/crates/circuits/sha-macros/tests/flags.rs b/crates/circuits/sha-macros/tests/flags.rs index cfd048f027..6da76c123d 100644 --- a/crates/circuits/sha-macros/tests/flags.rs +++ b/crates/circuits/sha-macros/tests/flags.rs @@ -1,4 +1,4 @@ -use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; #[repr(C)] diff --git a/crates/circuits/sha-macros/tests/nested.rs b/crates/circuits/sha-macros/tests/nested.rs index 82bf757964..2425791706 100644 --- a/crates/circuits/sha-macros/tests/nested.rs +++ b/crates/circuits/sha-macros/tests/nested.rs @@ -1,4 +1,4 @@ -use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; #[derive(ColsRef)] @@ -34,5 +34,8 @@ fn nested_from_mut() { let mut mut_input = [0; 1 + 1 + 32]; let mut mut_test: Test1ColsRefMut = Test1ColsRefMut::from::(&mut mut_input); let const_test: Test1ColsRef = Test1ColsRef::from_mut::(&mut mut_test); - println!("{}, {}, {}", const_test.a, const_test.nested.b, const_test.nested.c); + println!( + "{}, {}, {}", + const_test.a, const_test.nested.b, const_test.nested.c + ); } diff --git a/crates/circuits/sha-macros/tests/simple.rs b/crates/circuits/sha-macros/tests/simple.rs index b4c58bedab..cf89118c58 100644 --- a/crates/circuits/sha-macros/tests/simple.rs +++ b/crates/circuits/sha-macros/tests/simple.rs @@ -1,4 +1,4 @@ -use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; #[derive(ColsRef)] diff --git a/crates/circuits/sha-macros/tests/work-vars.rs b/crates/circuits/sha-macros/tests/work-vars.rs index e145bfffb1..6ca6d745cc 100644 --- a/crates/circuits/sha-macros/tests/work-vars.rs +++ b/crates/circuits/sha-macros/tests/work-vars.rs @@ -1,4 +1,4 @@ -use openvm_sha256_air::{Sha256Config, ShaConfig}; +use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; #[repr(C)] diff --git a/extensions/sha256/circuit/Cargo.toml b/extensions/sha256/circuit/Cargo.toml index 0c7100e99b..388cdf17ad 100644 --- a/extensions/sha256/circuit/Cargo.toml +++ b/extensions/sha256/circuit/Cargo.toml @@ -15,7 +15,7 @@ openvm-circuit = { workspace = true } openvm-instructions = { workspace = true } openvm-sha256-transpiler = { workspace = true } openvm-rv32im-circuit = { workspace = true } -openvm-sha256-air = { workspace = true } +openvm-sha-air = { workspace = true } derive-new.workspace = true derive_more = { workspace = true, features = ["from"] } diff --git a/extensions/sha256/circuit/src/sha256_chip/air.rs b/extensions/sha256/circuit/src/sha256_chip/air.rs index 0487314ea0..218bbe5603 100644 --- a/extensions/sha256/circuit/src/sha256_chip/air.rs +++ b/extensions/sha256/circuit/src/sha256_chip/air.rs @@ -11,11 +11,11 @@ use openvm_instructions::{ riscv::{RV32_CELL_BITS, RV32_MEMORY_AS, RV32_REGISTER_AS, RV32_REGISTER_NUM_LIMBS}, LocalOpcode, }; -use openvm_sha256_air::{ +use openvm_sha256_transpiler::Rv32Sha256Opcode; +use openvm_sha_air::{ compose, Sha256Air, SHA256_BLOCK_U8S, SHA256_HASH_WORDS, SHA256_ROUNDS_PER_ROW, SHA256_WORD_U16S, SHA256_WORD_U8S, }; -use openvm_sha256_transpiler::Rv32Sha256Opcode; use openvm_stark_backend::{ interaction::InteractionBuilder, p3_air::{Air, AirBuilder, BaseAir}, diff --git a/extensions/sha256/circuit/src/sha256_chip/columns.rs b/extensions/sha256/circuit/src/sha256_chip/columns.rs index a24014e51c..5c98f4de97 100644 --- a/extensions/sha256/circuit/src/sha256_chip/columns.rs +++ b/extensions/sha256/circuit/src/sha256_chip/columns.rs @@ -6,7 +6,7 @@ use openvm_circuit::{ }; use openvm_circuit_primitives::AlignedBorrow; use openvm_instructions::riscv::RV32_REGISTER_NUM_LIMBS; -use openvm_sha256_air::{Sha256DigestCols, Sha256RoundCols}; +use openvm_sha_air::{Sha256DigestCols, Sha256RoundCols}; use super::{SHA256_REGISTER_READS, SHA256_WRITE_SIZE}; diff --git a/extensions/sha256/circuit/src/sha256_chip/mod.rs b/extensions/sha256/circuit/src/sha256_chip/mod.rs index 5b9bf7bb46..6c8730b605 100644 --- a/extensions/sha256/circuit/src/sha256_chip/mod.rs +++ b/extensions/sha256/circuit/src/sha256_chip/mod.rs @@ -19,8 +19,8 @@ use openvm_instructions::{ LocalOpcode, }; use openvm_rv32im_circuit::adapters::read_rv32_register; -use openvm_sha256_air::{Sha256Air, SHA256_BLOCK_BITS}; use openvm_sha256_transpiler::Rv32Sha256Opcode; +use openvm_sha_air::{Sha256Air, SHA256_BLOCK_BITS}; use openvm_stark_backend::{interaction::BusIndex, p3_field::PrimeField32}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; diff --git a/extensions/sha256/circuit/src/sha256_chip/tests.rs b/extensions/sha256/circuit/src/sha256_chip/tests.rs index 55bc076e2c..db6199c813 100644 --- a/extensions/sha256/circuit/src/sha256_chip/tests.rs +++ b/extensions/sha256/circuit/src/sha256_chip/tests.rs @@ -6,8 +6,8 @@ use openvm_circuit_primitives::bitwise_op_lookup::{ BitwiseOperationLookupBus, SharedBitwiseOperationLookupChip, }; use openvm_instructions::{instruction::Instruction, riscv::RV32_CELL_BITS, LocalOpcode}; -use openvm_sha256_air::get_random_message; use openvm_sha256_transpiler::Rv32Sha256Opcode::{self, *}; +use openvm_sha_air::get_random_message; use openvm_stark_backend::{interaction::BusIndex, p3_field::FieldAlgebra}; use openvm_stark_sdk::{config::setup_tracing, p3_baby_bear::BabyBear, utils::create_seeded_rng}; use rand::{rngs::StdRng, Rng}; diff --git a/extensions/sha256/circuit/src/sha256_chip/trace.rs b/extensions/sha256/circuit/src/sha256_chip/trace.rs index 0d51a21368..746385f16a 100644 --- a/extensions/sha256/circuit/src/sha256_chip/trace.rs +++ b/extensions/sha256/circuit/src/sha256_chip/trace.rs @@ -3,7 +3,7 @@ use std::{array, borrow::BorrowMut, sync::Arc}; use openvm_circuit_primitives::utils::next_power_of_two_or_zero; use openvm_instructions::riscv::{RV32_CELL_BITS, RV32_REGISTER_NUM_LIMBS}; use openvm_rv32im_circuit::adapters::compose; -use openvm_sha256_air::{ +use openvm_sha_air::{ get_flag_pt_array, limbs_into_u32, Sha256Air, SHA256_BLOCK_WORDS, SHA256_BUFFER_SIZE, SHA256_H, SHA256_HASH_WORDS, SHA256_ROWS_PER_BLOCK, SHA256_WORD_U8S, }; From 13390a84c277619c6fa8c96f0a148be7d05d5503 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Wed, 12 Feb 2025 12:12:40 -0500 Subject: [PATCH 6/7] cleanup --- crates/circuits/sha-air/src/utils.rs | 5 +---- crates/circuits/sha-macros/Cargo.toml | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/circuits/sha-air/src/utils.rs b/crates/circuits/sha-air/src/utils.rs index 6a3d483833..0b8e357e03 100644 --- a/crates/circuits/sha-air/src/utils.rs +++ b/crates/circuits/sha-air/src/utils.rs @@ -5,10 +5,7 @@ use openvm_circuit_primitives::{ encoder::Encoder, utils::{not, select}, }; -use openvm_stark_backend::{ - p3_air::AirBuilder, - p3_field::{FieldAlgebra, PrimeField32}, -}; +use openvm_stark_backend::{p3_air::AirBuilder, p3_field::FieldAlgebra}; use rand::{rngs::StdRng, Rng}; use crate::{RotateRight, ShaConfig}; diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml index 0930f05abe..71ab68feeb 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/sha-macros/Cargo.toml @@ -9,7 +9,6 @@ repository.workspace = true [dependencies] syn = { version = "2.0", features = ["full", "extra-traits"] } quote = "1.0" -openvm-macros-common = { workspace = true, default-features = false } itertools = "0.14" proc-macro2 = "1.0" From eee18cd7059cff0714de36593907a14096f25429 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 28 Mar 2025 12:27:07 -0400 Subject: [PATCH 7/7] fix rebase issues --- Cargo.lock | 1091 ++++++++++++++++-------- crates/circuits/sha-air/src/air.rs | 34 +- crates/circuits/sha-air/src/columns.rs | 2 +- crates/circuits/sha-air/src/config.rs | 4 +- crates/circuits/sha-air/src/tests.rs | 92 +- crates/circuits/sha-air/src/trace.rs | 29 +- crates/circuits/sha-air/src/utils.rs | 2 - crates/circuits/sha-macros/src/lib.rs | 3 - 8 files changed, 853 insertions(+), 404 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ccead2b311..33438cbff0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,7 +37,7 @@ dependencies = [ "cfg-if", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -81,18 +81,18 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.21" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478bedf4d24e71ea48428d1bc278553bd7c6ae07c30ca063beb0b09fe58a9e74" +checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", - "derive_more 1.0.0", + "derive_more 2.0.1", "foldhash", "hashbrown 0.15.2", - "indexmap 2.7.1", + "indexmap 2.8.0", "itoa", "k256", "keccak-asm", @@ -125,7 +125,7 @@ checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "ark-ff" @@ -352,15 +352,21 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-trait" -version = "0.1.86" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "aurora-engine-modexp" version = "1.2.0" @@ -379,7 +385,7 @@ checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -390,9 +396,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-config" -version = "1.5.18" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90aff65e86db5fe300752551c1b015ef72b708ac54bded8ef43d0d53cb7cb0b1" +checksum = "8c39646d1a6b51240a1a23bb57ea4eebede7e16fbc237fdc876980233dcecb4f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -400,7 +406,7 @@ dependencies = [ "aws-sdk-ssooidc", "aws-sdk-sts", "aws-smithy-async", - "aws-smithy-http 0.61.1", + "aws-smithy-http", "aws-smithy-json", "aws-smithy-runtime", "aws-smithy-runtime-api", @@ -409,7 +415,7 @@ dependencies = [ "bytes", "fastrand", "hex", - "http 0.2.12", + "http 1.3.1", "ring", "time", "tokio", @@ -420,9 +426,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" +checksum = "4471bef4c22a06d2c7a1b6492493d3fdf24a805323109d6874f9c94d5906ac14" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -430,17 +436,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "aws-lc-rs" +version = "1.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "aws-runtime" -version = "1.5.5" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76dd04d39cc12844c0994f2c9c5a6f5184c22e9188ec1ff723de41910a21dcad" +checksum = "0aff45ffe35196e593ea3b9dd65b320e51e2dda95aff4390bc459e461d09c6ad" dependencies = [ "aws-credential-types", "aws-sigv4", "aws-smithy-async", "aws-smithy-eventstream", - "aws-smithy-http 0.60.12", + "aws-smithy-http", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -458,9 +487,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.78.0" +version = "1.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038614b6cf7dd68d9a7b5b39563d04337eb3678d1d4173e356e927b0356158a" +checksum = "3a36b09e8273d89c4f35ea122b83b30e48f906f3b644460d72a7d3656d1be93d" dependencies = [ "aws-credential-types", "aws-runtime", @@ -468,7 +497,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-checksums", "aws-smithy-eventstream", - "aws-smithy-http 0.61.1", + "aws-smithy-http", "aws-smithy-json", "aws-smithy-runtime", "aws-smithy-runtime-api", @@ -480,6 +509,7 @@ dependencies = [ "hex", "hmac", "http 0.2.12", + "http 1.3.1", "http-body 0.4.6", "lru", "once_cell", @@ -492,20 +522,21 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.61.0" +version = "1.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e65ff295979977039a25f5a0bf067a64bc5e6aa38f3cef4037cf42516265553c" +checksum = "b1cb45b83b53b5cd55ee33fd9fd8a70750255a3f286e4dca20e882052f2b256f" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", - "aws-smithy-http 0.61.1", + "aws-smithy-http", "aws-smithy-json", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", + "fastrand", "http 0.2.12", "once_cell", "regex-lite", @@ -514,20 +545,21 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.62.0" +version = "1.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91430a60f754f235688387b75ee798ef00cfd09709a582be2b7525ebb5306d4f" +checksum = "c8d4d9bc075ea6238778ed3951b65d3cde8c3864282d64fdcd19f2a90c0609f1" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", - "aws-smithy-http 0.61.1", + "aws-smithy-http", "aws-smithy-json", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", + "fastrand", "http 0.2.12", "once_cell", "regex-lite", @@ -536,14 +568,14 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.62.0" +version = "1.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9276e139d39fff5a0b0c984fc2d30f970f9a202da67234f948fda02e5bea1dbe" +checksum = "819ccba087f403890fee4825eeab460e64c59345667d2b83a12cf544b581e3a7" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", - "aws-smithy-http 0.61.1", + "aws-smithy-http", "aws-smithy-json", "aws-smithy-query", "aws-smithy-runtime", @@ -551,6 +583,7 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", + "fastrand", "http 0.2.12", "once_cell", "regex-lite", @@ -559,13 +592,13 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.2.9" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bfe75fad52793ce6dec0dc3d4b1f388f038b5eb866c8d4d7f3a8e21b5ea5051" +checksum = "69d03c3c05ff80d54ff860fe38c726f6f494c639ae975203a101335f223386db" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", - "aws-smithy-http 0.60.12", + "aws-smithy-http", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", @@ -574,7 +607,7 @@ dependencies = [ "hex", "hmac", "http 0.2.12", - "http 1.2.0", + "http 1.3.1", "once_cell", "p256 0.11.1", "percent-encoding", @@ -588,9 +621,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.4" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa59d1327d8b5053c54bf2eaae63bf629ba9e904434d0835a28ed3c0ed0a614e" +checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" dependencies = [ "futures-util", "pin-project-lite", @@ -599,11 +632,11 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.63.0" +version = "0.63.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2dc8d842d872529355c72632de49ef8c5a2949a4472f10e802f28cf925770c" +checksum = "b65d21e1ba6f2cdec92044f904356a19f5ad86961acf015741106cdfafd747c0" dependencies = [ - "aws-smithy-http 0.60.12", + "aws-smithy-http", "aws-smithy-types", "bytes", "crc32c", @@ -621,9 +654,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.7" +version = "0.60.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461e5e02f9864cba17cff30f007c2e37ade94d01e87cdb5204e44a84e6d38c17" +checksum = "7c45d3dddac16c5c59d553ece225a88870cf81b7b813c9cc17b78cf4685eac7a" dependencies = [ "aws-smithy-types", "bytes", @@ -632,16 +665,18 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.60.12" +version = "0.62.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7809c27ad8da6a6a68c454e651d4962479e81472aa19ae99e59f9aba1f9713cc" +checksum = "c5949124d11e538ca21142d1fba61ab0a2a2c1bc3ed323cdb3e4b878bfb83166" dependencies = [ + "aws-smithy-eventstream", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", "bytes-utils", "futures-core", "http 0.2.12", + "http 1.3.1", "http-body 0.4.6", "once_cell", "percent-encoding", @@ -651,35 +686,52 @@ dependencies = [ ] [[package]] -name = "aws-smithy-http" -version = "0.61.1" +name = "aws-smithy-http-client" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f276f21c7921fe902826618d1423ae5bf74cf8c1b8472aee8434f3dfd31824" +checksum = "8aff1159006441d02e57204bf57a1b890ba68bedb6904ffd2873c1c4c11c546b" dependencies = [ - "aws-smithy-eventstream", + "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", + "h2 0.4.8", "http 0.2.12", + "http 1.3.1", "http-body 0.4.6", - "once_cell", - "percent-encoding", + "hyper 0.14.32", + "hyper 1.6.0", + "hyper-rustls 0.24.2", + "hyper-rustls 0.27.5", + "hyper-util", "pin-project-lite", - "pin-utils", + "rustls 0.21.12", + "rustls 0.23.25", + "rustls-native-certs 0.8.1", + "rustls-pki-types", + "tokio", + "tower", "tracing", ] [[package]] name = "aws-smithy-json" -version = "0.61.2" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623a51127f24c30776c8b374295f2df78d92517386f77ba30773f15a30ce1422" +checksum = "92144e45819cae7dc62af23eac5a038a58aa544432d2102609654376a900bd07" dependencies = [ "aws-smithy-types", ] +[[package]] +name = "aws-smithy-observability" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445d065e76bc1ef54963db400319f1dd3ebb3e0a74af20f7f7630625b0cc7cc0" +dependencies = [ + "aws-smithy-runtime-api", + "once_cell", +] + [[package]] name = "aws-smithy-query" version = "0.60.7" @@ -692,42 +744,40 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.7.8" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d526a12d9ed61fadefda24abe2e682892ba288c2018bcb38b1b4c111d13f6d92" +checksum = "0152749e17ce4d1b47c7747bdfec09dac1ccafdcbc741ebf9daa2a373356730f" dependencies = [ "aws-smithy-async", - "aws-smithy-http 0.60.12", + "aws-smithy-http", + "aws-smithy-http-client", + "aws-smithy-observability", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", "fastrand", - "h2", "http 0.2.12", + "http 1.3.1", "http-body 0.4.6", "http-body 1.0.1", - "httparse", - "hyper", - "hyper-rustls", "once_cell", "pin-project-lite", "pin-utils", - "rustls", "tokio", "tracing", ] [[package]] name = "aws-smithy-runtime-api" -version = "1.7.3" +version = "1.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" +checksum = "3da37cf5d57011cb1753456518ec76e31691f1f474b73934a284eb2a1c76510f" dependencies = [ "aws-smithy-async", "aws-smithy-types", "bytes", "http 0.2.12", - "http 1.2.0", + "http 1.3.1", "pin-project-lite", "tokio", "tracing", @@ -736,16 +786,16 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.2.13" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b8a53819e42f10d0821f56da995e1470b199686a1809168db6ca485665f042" +checksum = "836155caafba616c0ff9b07944324785de2ab016141c3550bd1c07882f8cee8f" dependencies = [ "base64-simd", "bytes", "bytes-utils", "futures-core", "http 0.2.12", - "http 1.2.0", + "http 1.3.1", "http-body 0.4.6", "http-body 1.0.1", "http-body-util", @@ -771,9 +821,9 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.3.5" +version = "1.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbd0a668309ec1f66c0f6bda4840dd6d4796ae26d699ebc266d7cc95c6d040f" +checksum = "3873f8deed8927ce8d04487630dc9ff73193bab64742a61d050e57a68dec4125" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -841,9 +891,9 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.6.0" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "bincode" @@ -854,6 +904,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.100", + "which", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -871,9 +944,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitcode" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c1406a27371b2f76232a2259df6ab607b91b5a0a7476a7729ff590df5a969a" +checksum = "cf300f4aa6e66f3bdff11f1236a88c622fe47ea814524792240b4d554d9858ee" dependencies = [ "arrayvec", "bitcode_derive", @@ -890,14 +963,14 @@ checksum = "42b6b4cb608b8282dc3b53d0f4c9ab404655d562674c682db7e6c0458cc83c23" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bitvec" @@ -933,16 +1006,15 @@ dependencies = [ [[package]] name = "blake3" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1230237285e3e10cde447185e8975408ae24deaa67205ce684805c25bc0c7937" +checksum = "b17679a8d69b6d7fd9cd9801a536cec9fa5e5970b69f9d4747f70b39b031f5e7" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "memmap2", ] [[package]] @@ -981,9 +1053,9 @@ dependencies = [ [[package]] name = "bon" -version = "3.3.2" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7acc34ff59877422326db7d6f2d845a582b16396b6b08194942bf34c6528ab" +checksum = "65268237be94042665b92034f979c42d431d2fd998b49809543afe3e66abad1c" dependencies = [ "bon-macros", "rustversion", @@ -991,9 +1063,9 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.3.2" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4159dd617a7fbc9be6a692fe69dc2954f8e6bb6bb5e4d7578467441390d77fd0" +checksum = "803c95b2ecf650eb10b5f87dda6b9f6a1b758cee53245e2b7b825c9b3803a443" dependencies = [ "darling", "ident_case", @@ -1001,7 +1073,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1012,15 +1084,15 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" [[package]] name = "byteorder" @@ -1030,9 +1102,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "bytes-utils" @@ -1110,7 +1182,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver 1.0.25", + "semver 1.0.26", "serde", "serde_json", "thiserror 1.0.69", @@ -1124,15 +1196,24 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.14" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -1141,15 +1222,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-link", ] [[package]] @@ -1179,11 +1260,22 @@ dependencies = [ "half", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" -version = "4.5.30" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ "clap_builder", "clap_derive", @@ -1191,9 +1283,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.30" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" dependencies = [ "anstream", "anstyle", @@ -1203,14 +1295,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1219,6 +1311,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.3" @@ -1292,6 +1393,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1508,7 +1619,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1519,7 +1630,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1544,9 +1655,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" dependencies = [ "powerfmt", "serde", @@ -1571,7 +1682,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1582,7 +1693,7 @@ checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1595,7 +1706,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1604,7 +1715,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -1615,7 +1735,19 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", "unicode-xid", ] @@ -1648,7 +1780,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1657,11 +1789,17 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" [[package]] name = "ecdsa" @@ -1691,9 +1829,9 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elf" @@ -1730,7 +1868,7 @@ dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.5", "digest 0.10.7", - "ff 0.13.0", + "ff 0.13.1", "generic-array", "group 0.13.0", "pkcs8 0.10.2", @@ -1767,7 +1905,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1778,7 +1916,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -1792,9 +1930,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", @@ -1892,9 +2030,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "bitvec", "byteorder", @@ -1905,12 +2043,11 @@ dependencies = [ [[package]] name = "ff_derive" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f54704be45ed286151c5e11531316eaef5b8f5af7d597b806fdb8af108d84a" +checksum = "f10d12652036b0e99197587c6ba87a8fc3031986499973c030d8b44fcc151b60" dependencies = [ "addchain", - "cfg-if", "num-bigint 0.3.3", "num-integer", "num-traits", @@ -1939,9 +2076,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -1952,6 +2089,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -2027,26 +2170,26 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "getset" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded738faa0e88d3abc9d1a13cb11adc2073c400969eeb8793cf7132589959fc" +checksum = "f3586f256131df87204eb733da72e3d3eb4f343c639f4b7be279ac7c48baeafe" dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -2070,9 +2213,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fcdf9683c406c2fc4d124afd29c0d595e22210d633cbdb8695ba9935ab1dc6" +checksum = "bf3aa70d918d2b234126ff4f850f628f172542bf0603ded26b8ee36e5e22d5f9" [[package]] name = "glob" @@ -2098,7 +2241,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff 0.13.0", + "ff 0.13.1", "rand_core", "subtle", ] @@ -2115,7 +2258,26 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.7.1", + "indexmap 2.8.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap 2.8.0", "slab", "tokio", "tokio-util", @@ -2124,9 +2286,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" dependencies = [ "cfg-if", "crunchy", @@ -2149,7 +2311,7 @@ checksum = "62f0ca78d12ac5c893f286d7cdfe3869290305ab8cac376e2592cdc8396da102" dependencies = [ "blake2b_simd", "crossbeam", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "halo2curves-axiom", "itertools 0.11.0", @@ -2226,7 +2388,7 @@ checksum = "b756596082144af6e57105a20403b7b80fe9dccd085700b74fae3af523b74dba" dependencies = [ "blake2", "digest 0.10.7", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "halo2derive", "hex", @@ -2255,7 +2417,7 @@ checksum = "dd8309e4638b4f1bcf6613d72265a84074d26034c35edc5d605b5688e580b8b8" dependencies = [ "blake2b_simd", "digest 0.10.7", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "hex", "lazy_static", @@ -2329,9 +2491,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" [[package]] name = "hex" @@ -2357,6 +2519,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "http" version = "0.2.12" @@ -2370,9 +2541,9 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -2397,27 +2568,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.2.0", + "http 1.3.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.2.0", + "futures-core", + "http 1.3.1", "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -2435,7 +2606,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -2449,6 +2620,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.8", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -2457,24 +2648,62 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper", + "hyper 0.14.32", "log", - "rustls", - "rustls-native-certs", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http 1.3.1", + "hyper 1.6.0", + "hyper-util", + "rustls 0.23.25", + "rustls-native-certs 0.8.1", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.2", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -2529,9 +2758,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -2553,9 +2782,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -2574,9 +2803,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -2603,7 +2832,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -2650,7 +2879,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -2672,9 +2901,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2683,11 +2912,11 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi 0.5.0", "libc", "windows-sys 0.59.0", ] @@ -2718,9 +2947,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.14.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -2736,9 +2965,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" @@ -2814,11 +3043,17 @@ dependencies = [ "spin", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" -version = "0.2.169" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libgit2-sys" @@ -2832,6 +3067,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets", +] + [[package]] name = "libm" version = "0.2.11" @@ -2840,9 +3085,9 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libmimalloc-sys" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" dependencies = [ "cc", "libc", @@ -2850,9 +3095,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.21" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ "cc", "libc", @@ -2872,11 +3117,17 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" + [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "lockfree-object-pool" @@ -2886,9 +3137,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.25" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lru" @@ -2944,15 +3195,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memmap2" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" -dependencies = [ - "libc", -] - [[package]] name = "memuse" version = "0.2.2" @@ -2975,7 +3217,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62a6a1f7141f1d9bc7a886b87536bbfc97752e08b369e1e0453a9acfab5f5da4" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.8.0", "itoa", "lockfree-object-pool", "metrics", @@ -2996,7 +3238,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.14.5", - "indexmap 2.7.1", + "indexmap 2.8.0", "metrics", "num_cpus", "ordered-float", @@ -3007,18 +3249,24 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1" dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] @@ -3049,6 +3297,25 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3204,15 +3471,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b" [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openssl-probe" @@ -3268,7 +3535,7 @@ version = "0.1.0" dependencies = [ "openvm-macros-common", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3289,7 +3556,7 @@ version = "1.0.0-rc.2" dependencies = [ "openvm-macros-common", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3476,7 +3743,7 @@ version = "1.0.0-rc.2" dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3501,7 +3768,7 @@ version = "1.0.0-rc.2" dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3524,7 +3791,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3610,7 +3877,7 @@ version = "1.0.0-rc.2" dependencies = [ "openvm-macros-common", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3650,7 +3917,7 @@ dependencies = [ "quote", "strum", "strum_macros", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3719,7 +3986,7 @@ dependencies = [ name = "openvm-macros-common" version = "1.0.0-rc.2" dependencies = [ - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3799,7 +4066,7 @@ name = "openvm-native-compiler-derive" version = "1.0.0-rc.2" dependencies = [ "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -4105,22 +4372,10 @@ dependencies = [ ] [[package]] -name = "openvm-sha-macros" -version = "1.0.0-rc.0" -dependencies = [ - "itertools 0.14.0", - "ndarray", - "openvm-macros-common", - "openvm-sha256-air", - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "openvm-sha256-air" +name = "openvm-sha-air" version = "1.0.0-rc.2" dependencies = [ + "ndarray", "openvm-circuit", "openvm-circuit-primitives", "openvm-sha-macros", @@ -4130,6 +4385,18 @@ dependencies = [ "sha2", ] +[[package]] +name = "openvm-sha-macros" +version = "1.0.0-rc.2" +dependencies = [ + "itertools 0.14.0", + "ndarray", + "openvm-sha-air", + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "openvm-sha256-circuit" version = "1.0.0-rc.2" @@ -4223,7 +4490,7 @@ source = "git+https://github.com/openvm-org/stark-backend.git?rev=b051e8978da9c8 dependencies = [ "derivative", "derive_more 0.99.19", - "ff 0.13.0", + "ff 0.13.1", "itertools 0.14.0", "metrics", "metrics-tracing-context", @@ -4369,7 +4636,7 @@ name = "p3-bn254-fr" version = "0.1.0" source = "git+https://github.com/Plonky3/Plonky3.git?rev=88d7f05#88d7f059500fd956a7c1eb121e08653e5974728d" dependencies = [ - "ff 0.13.0", + "ff 0.13.1", "halo2curves", "num-bigint 0.4.6", "p3-field", @@ -4701,7 +4968,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -4726,7 +4993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" dependencies = [ "blake2b_simd", - "ff 0.13.0", + "ff 0.13.1", "group 0.13.0", "lazy_static", "rand", @@ -4748,12 +5015,12 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" dependencies = [ "memchr", - "thiserror 2.0.11", + "thiserror 2.0.12", "ucd-trie", ] @@ -4791,9 +5058,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plotters" @@ -4825,9 +5092,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "portable-atomic-util" @@ -4845,7 +5112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e4aaeda7a092e21165cc5f0cbc738e72a46f31c03c3cbd87b71ceae9d2d93bc" dependencies = [ "bitvec", - "ff 0.13.0", + "ff 0.13.1", "lazy_static", "log", "rand", @@ -4861,21 +5128,21 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy", + "zerocopy 0.8.24", ] [[package]] name = "prettyplease" -version = "0.2.29" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" dependencies = [ "proc-macro2", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -4891,9 +5158,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ "toml_edit", ] @@ -4917,14 +5184,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -4972,13 +5239,19 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "radium" version = "0.7.0" @@ -5036,9 +5309,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.4.0" +version = "11.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529468c1335c1c03919960dfefdb1b3648858c20d7ec2d0663e728e4a717efbc" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" dependencies = [ "bitflags", ] @@ -5206,9 +5479,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", @@ -5330,7 +5603,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.25", + "semver 1.0.26", ] [[package]] @@ -5342,7 +5615,20 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.3", "windows-sys 0.59.0", ] @@ -5354,10 +5640,24 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.103.1", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -5367,7 +5667,19 @@ dependencies = [ "openssl-probe", "rustls-pemfile", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.2.0", ] [[package]] @@ -5379,6 +5691,12 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pki-types" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -5389,11 +5707,23 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.103.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "rusty-fork" @@ -5409,9 +5739,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -5495,7 +5825,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -5522,9 +5865,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] @@ -5540,9 +5883,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] @@ -5567,22 +5910,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] name = "serde_json" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.8.0", "itoa", "memchr", "ryu", @@ -5608,7 +5951,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.1", + "indexmap 2.8.0", "serde", "serde_derive", "serde_json", @@ -5625,7 +5968,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5859,7 +6202,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5907,9 +6250,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -5924,7 +6267,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5941,15 +6284,14 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.17.1" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", - "getrandom 0.3.1", + "getrandom 0.3.2", "once_cell", - "rustix", + "rustix 1.0.3", "windows-sys 0.59.0", ] @@ -5971,7 +6313,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5982,7 +6324,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "test-case-core", ] @@ -6005,7 +6347,7 @@ checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6019,11 +6361,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -6034,18 +6376,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6089,9 +6431,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.37" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -6106,15 +6448,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -6151,9 +6493,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -6174,7 +6516,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6183,15 +6525,25 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls 0.23.25", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", @@ -6227,13 +6579,29 @@ version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.8.0", "serde", "serde_spanned", "toml_datetime", "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -6259,7 +6627,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6362,9 +6730,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" @@ -6431,9 +6799,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.13.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f41ffb7cf259f1ecc2876861a17e7142e63ead296f671f81f6ae85903e0d6" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" [[package]] name = "valuable" @@ -6508,9 +6876,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -6537,7 +6905,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -6559,7 +6927,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6583,6 +6951,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "winapi" version = "0.3.9" @@ -6623,6 +7003,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + [[package]] name = "windows-sys" version = "0.52.0" @@ -6707,18 +7093,18 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] @@ -6770,7 +7156,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "synstructure", ] @@ -6780,8 +7166,16 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive 0.8.24", ] [[package]] @@ -6792,27 +7186,38 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "synstructure", ] @@ -6833,7 +7238,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6855,7 +7260,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] diff --git a/crates/circuits/sha-air/src/air.rs b/crates/circuits/sha-air/src/air.rs index 49946f6f9e..fe44425df7 100644 --- a/crates/circuits/sha-air/src/air.rs +++ b/crates/circuits/sha-air/src/air.rs @@ -209,34 +209,44 @@ impl> ShaAir { // Assert that the previous hash + work vars == final hash. // That is, `next.prev_hash[i] + local.work_vars[i] == next.final_hash[i]` // where addition is done modulo 2^32 - for i in 0..SHA256_HASH_WORDS { + for i in 0..C::HASH_WORDS { let mut carry = AB::Expr::ZERO; - for j in 0..SHA256_WORD_U16S { - let work_var_limb = if i < SHA256_ROUNDS_PER_ROW { + for j in 0..C::WORD_U16S { + let work_var_limb = if i < C::ROUNDS_PER_ROW { compose::( - &local.work_vars.a[SHA256_ROUNDS_PER_ROW - 1 - i][j * 16..(j + 1) * 16], + &local + .work_vars + .a + .slice(s![C::ROUNDS_PER_ROW - 1 - i, j * 16..(j + 1) * 16]) + .as_slice().unwrap(), 1, ) } else { compose::( - &local.work_vars.e[SHA256_ROUNDS_PER_ROW + 3 - i][j * 16..(j + 1) * 16], + &local + .work_vars + .e + .slice(s![C::ROUNDS_PER_ROW + 3 - i, j * 16..(j + 1) * 16]) + .as_slice().unwrap(), 1, ) }; - let final_hash_limb = - compose::(&next.final_hash[i][j * 2..(j + 1) * 2], 8); + let final_hash_limb = compose::( + &next.final_hash.slice(s![i, j * 2..(j + 1) * 2]).as_slice().unwrap(), + 8, + ); carry = AB::Expr::from(AB::F::from_canonical_u32(1 << 16).inverse()) - * (next.prev_hash[i][j] + work_var_limb + carry - final_hash_limb); + * (next.prev_hash[[i,j]] + work_var_limb + carry - final_hash_limb); builder - .when(next.flags.is_digest_row) + .when(*next.flags.is_digest_row) .assert_bool(carry.clone()); } // constrain the final hash limbs two at a time since we can do two checks per interaction - for chunk in next.final_hash[i].chunks(2) { + for chunk in next.final_hash.row(i).as_slice().unwrap().chunks(2) { self.bitwise_lookup_bus .send_range(chunk[0], chunk[1]) - .eval(builder, next.flags.is_digest_row); + .eval(builder, *next.flags.is_digest_row); } } } @@ -364,7 +374,7 @@ impl> ShaAir { .assert_zero(*next_cols.flags.local_block_idx); self.eval_message_schedule(builder, local_cols.clone(), next_cols.clone()); - self.eval_work_vars(builder, local_cols, next_cols); + self.eval_work_vars(builder, local_cols.clone(), next_cols); let next_cols: ShaDigestColsRef = ShaDigestColsRef::from::(&next[start_col..start_col + C::DIGEST_WIDTH]); self.eval_digest_row(builder, local_cols, next_cols); diff --git a/crates/circuits/sha-air/src/columns.rs b/crates/circuits/sha-air/src/columns.rs index ab63922d0f..221c77e0f9 100644 --- a/crates/circuits/sha-air/src/columns.rs +++ b/crates/circuits/sha-air/src/columns.rs @@ -69,7 +69,7 @@ pub struct ShaMessageScheduleCols< const ROUNDS_PER_ROW: usize, const WORD_U8S: usize, > { - /// The message schedule words as 32-bit intergers + /// The message schedule words as 32-bit integers pub w: [[T; WORD_BITS]; ROUNDS_PER_ROW], /// 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 /// Note: carries are represented as 2 bit numbers diff --git a/crates/circuits/sha-air/src/config.rs b/crates/circuits/sha-air/src/config.rs index 919486d2c5..66dc32f96f 100644 --- a/crates/circuits/sha-air/src/config.rs +++ b/crates/circuits/sha-air/src/config.rs @@ -40,8 +40,6 @@ pub trait ShaConfig: Send + Sync + Clone { const ROUNDS_PER_ROW_MINUS_ONE: usize = Self::ROUNDS_PER_ROW - 1; /// Number of rounds per block. Must be a multiple of Self::ROUNDS_PER_ROW const ROUNDS_PER_BLOCK: usize; - /// Number of rows used to constrain rounds - const ROUND_ROWS: usize = Self::ROUNDS_PER_BLOCK / Self::ROUNDS_PER_ROW; /// Number of words in a SHA hash const HASH_WORDS: usize; /// Number of vars needed to encode the row index with [Encoder] @@ -85,7 +83,7 @@ pub trait ShaConfig: Send + Sync + Clone { /// To optimize the trace generation of invalid rows, we precompute those values. /// This trait also stores the constants K and H for the given SHA config. pub trait ShaPrecomputedValues { - // these should be appropirately sized for the config + // these should be appropriately sized for the config fn get_invalid_carry_a(round_num: usize) -> &'static [u32]; fn get_invalid_carry_e(round_num: usize) -> &'static [u32]; fn get_k() -> &'static [T]; diff --git a/crates/circuits/sha-air/src/tests.rs b/crates/circuits/sha-air/src/tests.rs index 4c567628de..8dbf4d07a4 100644 --- a/crates/circuits/sha-air/src/tests.rs +++ b/crates/circuits/sha-air/src/tests.rs @@ -1,4 +1,5 @@ -use std::{array, borrow::BorrowMut, cmp::max, sync::Arc}; +use std::{borrow::BorrowMut, cmp::max, sync::Arc}; +use crate::{ShaDigestColsRefMut, ShaRoundColsRefMut, ShaRoundColsRef}; use openvm_circuit::arch::{ instructions::riscv::RV32_CELL_BITS, @@ -22,8 +23,7 @@ use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; use crate::{ - compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, ShaFlagsColsRef, - ShaFlagsColsRefMut, ShaPrecomputedValues, + compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, ShaPrecomputedValues, }; // A wrapper AIR purely for testing purposes @@ -101,7 +101,7 @@ fn rand_sha_test + 'static>() { let bitwise_chip = SharedBitwiseOperationLookupChip::::new(bitwise_bus); let len = rng.gen_range(1..100); let random_records: Vec<_> = (0..len) - .map(|_| { + .map(|i| { ( (0..C::BLOCK_U8S) .map(|_| rng.gen::()) @@ -137,7 +137,7 @@ fn rand_sha512_test() { pub struct ShaTestBadFinalHashChip> { pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - pub records: Vec<(Vec, bool)>, // length of inner vec is C::BLOCK_U8S + pub records: Vec<(Vec, bool)>, // length of inner vec should be C::BLOCK_U8S } impl + 'static> Chip @@ -150,7 +150,7 @@ where } fn generate_air_proof_input(self) -> AirProofInput { - let mut trace = crate::generate_trace::>( + let mut trace = crate::generate_trace::, C>( &self.air.sub_air, self.bitwise_lookup_chip.clone(), self.records.clone(), @@ -161,7 +161,7 @@ where for (i, row) in self.records.iter().enumerate() { if row.1 { let last_digest_row_idx = (i + 1) * C::ROWS_PER_BLOCK - 1; - let last_digest_row: crate::ShaDigestColsRefMut> = + let mut last_digest_row: crate::ShaDigestColsRefMut> = ShaDigestColsRefMut::from::( trace.row_mut(last_digest_row_idx)[..C::DIGEST_WIDTH].borrow_mut(), ); @@ -176,10 +176,10 @@ where trace.row_pair_mut(last_digest_row_idx - 1, last_digest_row_idx); let last_round_row: crate::ShaRoundColsRefMut> = ShaRoundColsRefMut::from::(last_round_row.borrow_mut()); - let last_digest_row: crate::ShaRoundColsRefMut> = + let mut last_digest_row: crate::ShaRoundColsRefMut> = ShaRoundColsRefMut::from::(last_digest_row.borrow_mut()); // fix the intermed_4 for the digest row - generate_intermed_4(last_round_row, last_digest_row); + generate_intermed_4::, C>(&ShaRoundColsRef::from_mut::(&last_round_row), &mut last_digest_row); } } @@ -199,52 +199,72 @@ where // Copy of private method in Sha256Air used for testing /// Puts the correct intermed_4 in the `next_row` -fn generate_intermed_4( - local_cols: &Sha256RoundCols, - next_cols: &mut Sha256RoundCols, +fn generate_intermed_4>( + local_cols: &ShaRoundColsRef, + next_cols: &mut ShaRoundColsRefMut, ) { - let w = [local_cols.message_schedule.w, next_cols.message_schedule.w].concat(); - let w_limbs: Vec<[F; SHA256_WORD_U16S]> = w + let w = [ + local_cols + .message_schedule + .w + .rows() + .into_iter() + .collect::>(), + next_cols + .message_schedule + .w + .rows() + .into_iter() + .collect::>(), + ] + .concat(); + + + // length of inner vec is C::WORD_U16S + let w_limbs: Vec> = w .iter() - .map(|x| array::from_fn(|i| compose::(&x[i * 16..(i + 1) * 16], 1))) + .map(|x| { + (0..C::WORD_U16S) + .map(|i| compose::(&x.as_slice().unwrap()[i * 16..(i + 1) * 16], 1)) + .collect::>() + }) .collect(); - for i in 0..SHA256_ROUNDS_PER_ROW { - let sig_w = small_sig0_field::(&w[i + 1]); - let sig_w_limbs: [F; SHA256_WORD_U16S] = - array::from_fn(|j| compose::(&sig_w[j * 16..(j + 1) * 16], 1)); + for i in 0..C::ROUNDS_PER_ROW { + let sig_w = small_sig0_field::(w[i + 1].as_slice().unwrap()); + let sig_w_limbs: Vec = (0..C::WORD_U16S) + .map(|j| compose::(&sig_w[j * 16..(j + 1) * 16], 1)) + .collect(); for (j, sig_w_limb) in sig_w_limbs.iter().enumerate() { - next_cols.schedule_helper.intermed_4[i][j] = w_limbs[i][j] + *sig_w_limb; + next_cols.schedule_helper.intermed_4[[i, j]] = w_limbs[i][j] + *sig_w_limb; } } } -impl ChipUsageGetter for Sha256TestBadFinalHashChip { +impl> ChipUsageGetter for ShaTestBadFinalHashChip { fn air_name(&self) -> String { get_air_name(&self.air) } fn current_trace_height(&self) -> usize { - self.records.len() * SHA256_ROWS_PER_BLOCK + self.records.len() * C::ROWS_PER_BLOCK } fn trace_width(&self) -> usize { - max(SHA256_ROUND_WIDTH, SHA256_DIGEST_WIDTH) + max(C::ROUND_WIDTH, C::DIGEST_WIDTH) } } -#[test] -#[should_panic] -fn test_sha256_final_hash_constraints() { +fn test_sha_final_hash_constraints + 'static>() { let mut rng = create_seeded_rng(); let tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); let bitwise_chip = SharedBitwiseOperationLookupChip::::new(bitwise_bus); let len = rng.gen_range(1..100); let random_records: Vec<_> = (0..len) - .map(|_| (array::from_fn(|_| rng.gen::()), true)) + .map(|_| ((0..C::BLOCK_U8S).map(|_| rng.gen::()).collect::>(), true)) .collect(); - let chip = Sha256TestBadFinalHashChip { - air: Sha256TestAir { - sub_air: Sha256Air::new(bitwise_bus, SELF_BUS_IDX), + let chip = ShaTestBadFinalHashChip { + air: ShaTestAir { + sub_air: ShaAir::::new(bitwise_bus, SELF_BUS_IDX), }, bitwise_lookup_chip: bitwise_chip.clone(), records: random_records, @@ -253,3 +273,15 @@ fn test_sha256_final_hash_constraints() { let tester = tester.build().load(chip).load(bitwise_chip).finalize(); tester.simple_test().expect("Verification failed"); } + +#[test] +#[should_panic] +fn test_sha256_final_hash_constraints() { + test_sha_final_hash_constraints::(); +} + +#[test] +#[should_panic] +fn test_sha512_final_hash_constraints() { + test_sha_final_hash_constraints::(); +} diff --git a/crates/circuits/sha-air/src/trace.rs b/crates/circuits/sha-air/src/trace.rs index 4bdc291efc..fe294a430f 100644 --- a/crates/circuits/sha-air/src/trace.rs +++ b/crates/circuits/sha-air/src/trace.rs @@ -339,9 +339,10 @@ impl> ShaAir { let final_hash: Vec = (0..C::HASH_WORDS) .map(|i| work_vars[i].wrapping_add(prev_hash[i])) .collect(); - let final_hash_limbs: Vec> = final_hash.iter().map(|i| - word_into_u8_limbs::(final_hash[i]) - ) + let final_hash_limbs: Vec> = final_hash + .iter() + .map(|word| word_into_u8_limbs::(*word)) + .collect(); // need to ensure final hash limbs are bytes, in order for // prev_hash[i] + work_vars[i] == final_hash[i] // to be constrained correctly @@ -368,7 +369,7 @@ impl> ShaAir { .collect::>() })) .for_each(|(x, y)| *x = y); - + let hash = if is_last_block { C::get_h() .iter() @@ -476,11 +477,20 @@ impl> ShaAir { &mut next_block_first_row[trace_start_col..trace_start_col + C::ROUND_WIDTH], ); // Fill in the last round row's `intermed_12` with dummy values so the message schedule constraints holds on row 16 - Self::generate_intermed_12(&mut cols_last_round_row, ShaRoundColsRef::from_mut::(&cols_digest_row)); + Self::generate_intermed_12( + &mut cols_last_round_row, + ShaRoundColsRef::from_mut::(&cols_digest_row), + ); // Fill in the digest row's `intermed_12` with dummy values so the message schedule constraints holds on the next block's row 0 - Self::generate_intermed_12(&mut cols_digest_row, ShaRoundColsRef::from_mut::(&cols_next_block_first_row)); + Self::generate_intermed_12( + &mut cols_digest_row, + ShaRoundColsRef::from_mut::(&cols_next_block_first_row), + ); // Fill in the next block's first row's `intermed_4` with dummy values so the message schedule constraints holds on that row - Self::generate_intermed_4(ShaRoundColsRef::from_mut::(&cols_digest_row), &mut cols_next_block_first_row); + Self::generate_intermed_4( + ShaRoundColsRef::from_mut::(&cols_digest_row), + &mut cols_next_block_first_row, + ); } /// Fills the `cols` as a padding row @@ -796,9 +806,8 @@ pub fn generate_trace( - &(0..C::WORD_U8S).map(|j| - input[((i + 1) * C::WORD_U8S - j - 1] - ) + &(0..C::WORD_U8S) + .map(|j| input[(i + 1) * C::WORD_U8S - j - 1] as u32) .collect::>(), ) }) diff --git a/crates/circuits/sha-air/src/utils.rs b/crates/circuits/sha-air/src/utils.rs index 0b8e357e03..417e741c09 100644 --- a/crates/circuits/sha-air/src/utils.rs +++ b/crates/circuits/sha-air/src/utils.rs @@ -1,5 +1,3 @@ -use std::array; - pub use openvm_circuit_primitives::utils::compose; use openvm_circuit_primitives::{ encoder::Encoder, diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs index 9fc75ea264..3b446642e3 100644 --- a/crates/circuits/sha-macros/src/lib.rs +++ b/crates/circuits/sha-macros/src/lib.rs @@ -1,9 +1,6 @@ -#![feature(proc_macro_diagnostic)] - extern crate proc_macro; use itertools::Itertools; -//use openvm_macros_common::MacroArgs; use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::{parse_macro_input, parse_quote, DeriveInput, Expr};