From 66eab32603eaf2e5115296fda7543977d54bb574 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Thu, 6 Feb 2025 13:35:18 -0500 Subject: [PATCH 01/27] 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 0de21f22b6..eacd74b39e 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" dependencies = [ "openvm-circuit", "openvm-circuit-primitives", + "openvm-sha-macros", "openvm-stark-backend", "openvm-stark-sdk", "rand", @@ -4789,6 +4828,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" @@ -4994,6 +5042,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 943b8d798e..c88560a2ae 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 ea45bc866fed42b718a67f1c27dd5263de9df727 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 10 Feb 2025 16:00:40 -0500 Subject: [PATCH 02/27] 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 43f37150d6a301b3013563055cd6188975c73187 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 10 Feb 2025 16:08:36 -0500 Subject: [PATCH 03/27] 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 dc8938d95b888ec700a8d04205b90f7dc8a301c3 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 10 Feb 2025 17:10:28 -0500 Subject: [PATCH 04/27] 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 eacd74b39e..3bad5d4958 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 d743bdc63c1d85ea3ece9032cacac0ac22fd43be Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Wed, 12 Feb 2025 12:04:25 -0500 Subject: [PATCH 05/27] Updated names --- 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 +- 21 files changed, 50 insertions(+), 78 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/Cargo.lock b/Cargo.lock index 3bad5d4958..23a019b515 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 c88560a2ae..eb2d023205 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,7 +112,7 @@ openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", ta 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 926317aab7b2a0df75335579abbca18ecded3c1d Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Wed, 12 Feb 2025 12:12:40 -0500 Subject: [PATCH 06/27] 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 2f735308487c5979819b2e0705de2678efe1a9ad Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 28 Mar 2025 12:27:07 -0400 Subject: [PATCH 07/27] fix rebase issues --- Cargo.lock | 1064 ++++++++++++++++-------- 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, 840 insertions(+), 390 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23a019b515..76a195ac82 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 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", - "tokio-rustls", + "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" dependencies = [ "openvm-macros-common", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3476,7 +3743,7 @@ version = "1.0.0" dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3501,7 +3768,7 @@ version = "1.0.0" 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" 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" dependencies = [ - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -3799,7 +4066,7 @@ name = "openvm-native-compiler-derive" version = "1.0.0" dependencies = [ "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -4121,6 +4388,7 @@ dependencies = [ name = "openvm-sha256-air" version = "1.0.0" dependencies = [ + "ndarray", "openvm-circuit", "openvm-circuit-primitives", "openvm-sha-macros", @@ -4223,7 +4491,7 @@ source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.0.0#884f8e6 dependencies = [ "derivative", "derive_more 0.99.19", - "ff 0.13.0", + "ff 0.13.1", "itertools 0.14.0", "metrics", "metrics-tracing-context", @@ -4368,7 +4636,7 @@ name = "p3-bn254-fr" version = "0.1.0" source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" dependencies = [ - "ff 0.13.0", + "ff 0.13.1", "halo2curves", "num-bigint 0.4.6", "p3-field", @@ -4700,7 +4968,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -4725,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", @@ -4747,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", ] @@ -4790,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" @@ -4824,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" @@ -4844,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", @@ -4860,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]] @@ -4890,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", ] @@ -4916,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", ] @@ -4971,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" @@ -5035,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", ] @@ -5205,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", @@ -5329,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]] @@ -5341,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", ] @@ -5353,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" @@ -5366,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]] @@ -5378,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" @@ -5388,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" @@ -5408,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" @@ -5494,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", @@ -5521,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", ] @@ -5539,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", ] @@ -5566,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", @@ -5607,7 +5951,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.1", + "indexmap 2.8.0", "serde", "serde_derive", "serde_json", @@ -5624,7 +5968,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5858,7 +6202,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5906,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", @@ -5923,7 +6267,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5940,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", ] @@ -5970,7 +6313,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -5981,7 +6324,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "test-case-core", ] @@ -6004,7 +6347,7 @@ checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6018,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]] @@ -6033,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]] @@ -6088,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", @@ -6105,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", @@ -6150,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", @@ -6173,7 +6516,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6182,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", @@ -6226,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" @@ -6258,7 +6627,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6361,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" @@ -6430,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" @@ -6507,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", ] @@ -6536,7 +6905,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -6558,7 +6927,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6582,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" @@ -6622,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" @@ -6706,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", ] @@ -6769,7 +7156,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", "synstructure", ] @@ -6779,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]] @@ -6791,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", ] @@ -6832,7 +7238,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.100", ] [[package]] @@ -6854,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}; From ef25bdcec8be3c91cb0a99aa37ea15d125a55d47 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Thu, 13 Feb 2025 16:50:55 -0500 Subject: [PATCH 08/27] Merge ShaPrecomputedValues trait into ShaConfig trait for simplicity --- crates/circuits/sha-air/src/air.rs | 15 +++---- crates/circuits/sha-air/src/columns.rs | 6 +++ crates/circuits/sha-air/src/config.rs | 60 ++++++++++++-------------- crates/circuits/sha-air/src/tests.rs | 29 +++++-------- crates/circuits/sha-air/src/trace.rs | 8 ++-- 5 files changed, 54 insertions(+), 64 deletions(-) diff --git a/crates/circuits/sha-air/src/air.rs b/crates/circuits/sha-air/src/air.rs index fe44425df7..225a1c791c 100644 --- a/crates/circuits/sha-air/src/air.rs +++ b/crates/circuits/sha-air/src/air.rs @@ -19,13 +19,12 @@ use super::{ small_sig1_field, }; use crate::{ - constraint_word_addition, word_into_u16_limbs, ShaConfig, ShaDigestColsRef, - ShaPrecomputedValues, ShaRoundColsRef, + constraint_word_addition, word_into_u16_limbs, ShaConfig, ShaDigestColsRef, ShaRoundColsRef, }; /// Expects the message to be padded to a multiple of C::BLOCK_WORDS * C::WORD_BITS bits #[derive(Clone, Debug)] -pub struct ShaAir> { +pub struct ShaAir { pub bitwise_lookup_bus: BitwiseOperationLookupBus, pub row_idx_encoder: Encoder, /// Internal bus for self-interactions in this AIR. @@ -33,7 +32,7 @@ pub struct ShaAir> { _phantom: PhantomData, } -impl> ShaAir { +impl ShaAir { pub fn new(bitwise_lookup_bus: BitwiseOperationLookupBus, self_bus_idx: BusIndex) -> Self { Self { bitwise_lookup_bus, @@ -44,15 +43,13 @@ impl> ShaAir { } } -impl> BaseAir for ShaAir { +impl BaseAir for ShaAir { fn width(&self) -> usize { max(C::ROUND_WIDTH, C::DIGEST_WIDTH) } } -impl> SubAir - for ShaAir -{ +impl SubAir for ShaAir { /// The start column for the sub-air to use type AirContext<'a> = usize @@ -72,7 +69,7 @@ impl> SubAi } } -impl> ShaAir { +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) { diff --git a/crates/circuits/sha-air/src/columns.rs b/crates/circuits/sha-air/src/columns.rs index 221c77e0f9..938cd2c3c7 100644 --- a/crates/circuits/sha-air/src/columns.rs +++ b/crates/circuits/sha-air/src/columns.rs @@ -20,6 +20,7 @@ use crate::ShaConfig; /// 2. Specific constraints to use the appropriate struct, with flags helping to do conditional constraints #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] pub struct ShaRoundCols< T, const WORD_BITS: usize, @@ -38,6 +39,7 @@ pub struct ShaRoundCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] pub struct ShaDigestCols< T, const WORD_BITS: usize, @@ -63,6 +65,7 @@ pub struct ShaDigestCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] pub struct ShaMessageScheduleCols< T, const WORD_BITS: usize, @@ -78,6 +81,7 @@ pub struct ShaMessageScheduleCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] pub struct ShaWorkVarsCols< T, const WORD_BITS: usize, @@ -96,6 +100,7 @@ pub struct ShaWorkVarsCols< /// Note: these need to be correctly assigned for every row even on padding rows #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] pub struct ShaMessageHelperCols< T, const WORD_U16S: usize, @@ -114,6 +119,7 @@ pub struct ShaMessageHelperCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] 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 diff --git a/crates/circuits/sha-air/src/config.rs b/crates/circuits/sha-air/src/config.rs index 66dc32f96f..871ed866ab 100644 --- a/crates/circuits/sha-air/src/config.rs +++ b/crates/circuits/sha-air/src/config.rs @@ -86,8 +86,8 @@ pub trait ShaPrecomputedValues { // 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]; - fn get_h() -> &'static [T]; + fn get_k() -> &'static [Self::Word]; + fn get_h() -> &'static [Self::Word]; } #[derive(Clone)] @@ -110,6 +110,19 @@ impl ShaConfig for Sha256Config { const HASH_WORDS: usize = 8; /// Number of vars needed to encode the row index with [Encoder] const ROW_VAR_CNT: usize = 5; + + 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 + } } pub const SHA256_INVALID_CARRY_A: [[u32; Sha256Config::WORD_U16S]; Sha256Config::ROUNDS_PER_ROW] = [ @@ -141,21 +154,6 @@ 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; @@ -176,6 +174,19 @@ impl ShaConfig for Sha512Config { const HASH_WORDS: usize = 8; /// Number of vars needed to encode the row index with [Encoder] const ROW_VAR_CNT: usize = 6; + + 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 + } } pub(crate) const SHA512_INVALID_CARRY_A: [[u32; Sha512Config::WORD_U16S]; @@ -289,21 +300,6 @@ pub const SHA512_H: [u64; 8] = [ 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 // not sure why this doesn't inf loop pub trait RotateRight { diff --git a/crates/circuits/sha-air/src/tests.rs b/crates/circuits/sha-air/src/tests.rs index 8dbf4d07a4..a086d34747 100644 --- a/crates/circuits/sha-air/src/tests.rs +++ b/crates/circuits/sha-air/src/tests.rs @@ -23,46 +23,37 @@ use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; use crate::{ - compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, ShaPrecomputedValues, + compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, }; // A wrapper AIR purely for testing purposes #[derive(Clone, Debug)] -pub struct ShaTestAir> { +pub struct ShaTestAir { pub sub_air: ShaAir, } -impl> BaseAirWithPublicValues - for ShaTestAir -{ -} -impl> PartitionedBaseAir - for ShaTestAir -{ -} -impl> BaseAir for ShaTestAir { +impl BaseAirWithPublicValues for ShaTestAir {} +impl PartitionedBaseAir for ShaTestAir {} +impl BaseAir for ShaTestAir { fn width(&self) -> usize { as BaseAir>::width(&self.sub_air) } } -impl> Air - for ShaTestAir -{ +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 ShaTestChip> { +pub struct ShaTestChip { pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, pub records: Vec<(Vec, bool)>, // length of inner vec is BLOCK_U8S } -impl + 'static> Chip - for ShaTestChip +impl Chip for ShaTestChip where Val: PrimeField32, { @@ -80,7 +71,7 @@ where } } -impl> ChipUsageGetter for ShaTestChip { +impl ChipUsageGetter for ShaTestChip { fn air_name(&self) -> String { get_air_name(&self.air) } @@ -94,7 +85,7 @@ impl> ChipUsageGetter for ShaTestCh } const SELF_BUS_IDX: BusIndex = 28; -fn rand_sha_test + 'static>() { +fn rand_sha_test() { let mut rng = create_seeded_rng(); let tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); diff --git a/crates/circuits/sha-air/src/trace.rs b/crates/circuits/sha-air/src/trace.rs index fe294a430f..2886ca72df 100644 --- a/crates/circuits/sha-air/src/trace.rs +++ b/crates/circuits/sha-air/src/trace.rs @@ -15,14 +15,14 @@ use super::{ }; use crate::{ 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, + word_into_u16_limbs, word_into_u8_limbs, ShaConfig, ShaDigestColsRefMut, ShaRoundColsRef, + WrappingAdd, }; /// 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 { +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: &[C::Word], input: Vec) -> Vec { @@ -749,7 +749,7 @@ impl> ShaAir { } /// `records` consists of pairs of `(input_block, is_last_block)`. -pub fn generate_trace>( +pub fn generate_trace( sub_air: &ShaAir, bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, records: Vec<(Vec, bool)>, From d110b70df81439d8a3d12f2edabfbc3ea83de55f Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Thu, 13 Feb 2025 16:52:17 -0500 Subject: [PATCH 09/27] Generalize ColsRef macro - allow using traits other than ShaConfig for const parameters - support fields types that derive AlignedBorrow (not recursed into) - support nested-array-type fields with literal array lengths - support nested-array-type fields with constant array lengths --- crates/circuits/sha-macros/Cargo.toml | 3 +- crates/circuits/sha-macros/src/lib.rs | 230 +++++++++++++----- crates/circuits/sha-macros/tests/arrays.rs | 19 ++ .../sha-macros/tests/const-len-arrays.rs | 27 ++ crates/circuits/sha-macros/tests/flags.rs | 1 + crates/circuits/sha-macros/tests/nested.rs | 2 + crates/circuits/sha-macros/tests/plain.rs | 53 ++++ crates/circuits/sha-macros/tests/simple.rs | 1 + .../circuits/sha-macros/tests/test_config.rs | 7 + crates/circuits/sha-macros/tests/work-vars.rs | 1 + 10 files changed, 282 insertions(+), 62 deletions(-) create mode 100644 crates/circuits/sha-macros/tests/arrays.rs create mode 100644 crates/circuits/sha-macros/tests/const-len-arrays.rs create mode 100644 crates/circuits/sha-macros/tests/plain.rs create mode 100644 crates/circuits/sha-macros/tests/test_config.rs diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml index 71ab68feeb..af434f1c1a 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/sha-macros/Cargo.toml @@ -14,7 +14,8 @@ proc-macro2 = "1.0" [dev-dependencies] openvm-sha-air = { workspace = true } -ndarray = "0.16" +openvm-circuit-primitives-derive = { workspace = true } +ndarray.workspace = true [lib] proc-macro = true diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs index 3b446642e3..bccb6636a3 100644 --- a/crates/circuits/sha-macros/src/lib.rs +++ b/crates/circuits/sha-macros/src/lib.rs @@ -3,24 +3,41 @@ extern crate proc_macro; use itertools::Itertools; use proc_macro::TokenStream; use quote::{format_ident, quote}; -use syn::{parse_macro_input, parse_quote, DeriveInput, Expr}; +use syn::{parse_macro_input, parse_quote, DeriveInput}; -#[proc_macro_derive(ColsRef, attributes(dim))] +#[proc_macro_derive(ColsRef, attributes(plain, config))] 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()) + let config = derive_input + .attrs + .iter() + .find(|attr| attr.path().is_ident("config")); + if config.is_none() { + return syn::Error::new(derive_input.ident.span(), "Config attribute is required") .to_compile_error() .into(); + } + let config: proc_macro2::Ident = config + .unwrap() + .parse_args() + .expect("Failed to parse config"); + + let span = derive_input.ident.span(); + let res = cols_ref_impl(derive_input, config); + if res.is_err() { + 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 { +fn cols_ref_impl( + derive_input: DeriveInput, + config: proc_macro2::Ident, +) -> Result { let DeriveInput { ident, generics, @@ -47,12 +64,14 @@ fn cols_ref_impl(derive_input: DeriveInput) -> Result { let const_field_infos: Vec = data_struct .fields .iter() - .map(|f| get_const_cols_ref_fields(f, generic_type)) + .map(|f| get_const_cols_ref_fields(f, generic_type, &const_generics)) .collect::, String>>() .map_err(|e| format!("Failed to process fields. {}", e))?; @@ -69,14 +88,14 @@ fn cols_ref_impl(derive_input: DeriveInput) -> Result = data_struct .fields .iter() - .map(|f| get_mut_cols_ref_fields(f, generic_type)) + .map(|f| get_mut_cols_ref_fields(f, generic_type, &const_generics)) .collect::, String>>() .map_err(|e| format!("Failed to process fields. {}", e))?; @@ -93,7 +112,7 @@ fn cols_ref_impl(derive_input: DeriveInput) -> Result proc_macro2::TokenStream { +fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_macro2::TokenStream { let StructInfo { name, vis, @@ -152,21 +171,24 @@ fn make_struct(struct_info: StructInfo) -> proc_macro2::TokenStream { } impl<'a, #generic_type> #name<'a, #generic_type> { - pub fn from(#from_args) -> Self { + pub fn from(#from_args) -> Self { #( #prepare_subslices )* Self { #( #idents: #initializers ),* } } - pub fn len() -> usize { + pub fn len() -> usize { 0 #( + #length_exprs )* } } } } -fn make_from_mut(struct_info: StructInfo) -> Result { +fn make_from_mut( + struct_info: StructInfo, + config: &proc_macro2::Ident, +) -> Result { let StructInfo { name, vis: _, @@ -188,30 +210,38 @@ fn make_from_mut(struct_info: StructInfo) -> Result { - 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 + + if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) { + Ok(quote! { + other.#ident + }) + } else { + 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 + other.#ident.view() }) } + _ => Err(format!("Unsupported type: {:?}", f.ty)), } - syn::Type::Array(_) => { - // type is nested array of T - Ok(quote! { - other.#ident.view() - }) - } - _ => Err(format!("Unsupported type: {:?}", f.ty)), } }) .collect::, String>>()?; @@ -228,7 +258,7 @@ fn make_from_mut(struct_info: StructInfo) -> Result #name<'b, #generic_type> { - pub fn from_mut<'a, C: ShaConfig>(other: &'b #mut_struct_type) -> Self + pub fn from_mut<'a, C: #config>(other: &'b #mut_struct_type) -> Self { Self { #( #field_idents: #from_mut_impl ),* @@ -255,9 +285,34 @@ struct FieldInfo { fn get_const_cols_ref_fields( f: &syn::Field, generic_type: &syn::TypeParam, + const_generics: &[&syn::Ident], ) -> Result { let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); + + if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) { + // treat the field as a struct that derives AlignedBorrow + let f_ty = &f.ty; + return Ok(FieldInfo { + ty: parse_quote! { + &'a #f_ty + }, + length_expr: quote! { + <#f_ty>::width() + }, + prepare_subslice: quote! { + let #length_var = <#f_ty>::width(); + let (#slice_var, slice) = slice.split_at(#length_var); + }, + initializer: quote! { + { + use core::borrow::Borrow; + #slice_var.borrow() + } + }, + }); + } + match get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }) { Some(const_cols_ref_type) => Ok(FieldInfo { ty: parse_quote! { @@ -277,7 +332,7 @@ fn get_const_cols_ref_fields( }), 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| { + let dims = get_dims(&f.ty, const_generics).map_err(|e| { format!( "Failed to parse the type of the field '{}'. {}", f.ident.clone().unwrap(), @@ -308,17 +363,26 @@ fn get_const_cols_ref_fields( let ndarray_type: syn::Type = parse_quote! { ndarray::#ndarray_ident<'a, #generic_type> }; + let dim_exprs = dims + .iter() + .map(|d| match d { + // need to prepend C:: for const generic array dimensions + Dimension::ConstGeneric(expr) => quote! { C::#expr }, + Dimension::Other(expr) => quote! { #expr }, + }) + .collect_vec(); + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + Ok(FieldInfo { ty: parse_quote! { #ndarray_type }, - length_expr: quote! { - 1 #(* C::#dims)* - }, + length_expr: length_expr.clone(), 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(); + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); }, initializer: quote! { #slice_var @@ -333,9 +397,34 @@ fn get_const_cols_ref_fields( fn get_mut_cols_ref_fields( f: &syn::Field, generic_type: &syn::TypeParam, + const_generics: &[&syn::Ident], ) -> Result { let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); + + if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) { + // treat the field as a struct that derives AlignedBorrow + let f_ty = &f.ty; + return Ok(FieldInfo { + ty: parse_quote! { + &'a mut #f_ty + }, + length_expr: quote! { + <#f_ty>::width() + }, + prepare_subslice: quote! { + let #length_var = <#f_ty>::width(); + let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); + }, + initializer: quote! { + { + use core::borrow::BorrowMut; + #slice_var.borrow_mut() + } + }, + }); + } + match get_mut_cols_ref_type(&f.ty, generic_type) { Some(mut_cols_ref_type) => Ok(FieldInfo { ty: parse_quote! { @@ -355,7 +444,7 @@ fn get_mut_cols_ref_fields( }), 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| { + let dims = get_dims(&f.ty, const_generics).map_err(|e| { format!( "Failed to parse the type of the field '{}'. {}", f.ident.clone().unwrap(), @@ -386,17 +475,25 @@ fn get_mut_cols_ref_fields( let ndarray_type: syn::Type = parse_quote! { ndarray::#ndarray_ident<'a, #generic_type> }; + let dim_exprs = dims + .iter() + .map(|d| match d { + // need to prepend C:: for const generic array dimensions + Dimension::ConstGeneric(expr) => quote! { C::#expr }, + Dimension::Other(expr) => quote! { #expr }, + }) + .collect_vec(); + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; Ok(FieldInfo { ty: parse_quote! { #ndarray_type }, - length_expr: quote! { - 1 #(* C::#dims)* - }, + length_expr: length_expr.clone(), 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(); + let (mut #slice_var, mut slice) = slice.split_at_mut(#length_expr); + let mut #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); }, initializer: quote! { #slice_var @@ -451,23 +548,34 @@ fn get_mut_cols_ref_type(ty: &syn::Type, generic_type: &syn::TypeParam) -> Optio } } -fn get_dims(ty: &syn::Type) -> Result, String> { - get_dims_impl(ty).map(|dims| dims.into_iter().rev().collect()) +// Type of array dimension +enum Dimension { + ConstGeneric(syn::Expr), + Other(syn::Expr), +} +fn get_dims(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Result, String> { + get_dims_impl(ty, const_generics).map(|dims| dims.into_iter().rev().collect()) } -fn get_dims_impl(ty: &syn::Type) -> Result, String> { +fn get_dims_impl(ty: &syn::Type, const_generics: &[&syn::Ident]) -> 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()), + let mut dims = get_dims_impl(array.elem.as_ref(), const_generics)?; + match &array.len { + syn::Expr::Path(syn::ExprPath { path, .. }) => { + let len_ident = path.get_ident(); + if len_ident.is_some() && const_generics.contains(&len_ident.unwrap()) { + dims.push(Dimension::ConstGeneric(array.len.clone())); + } else { + dims.push(Dimension::Other(array.len.clone())); + } + } + syn::Expr::Lit(expr_lit) => dims.push(Dimension::Other(expr_lit.clone().into())), + _ => return Err("Unsupported array length type".to_string()), } Ok(dims) } syn::Type::Path(_) => Ok(Vec::new()), - _ => Err( - "Only generic types and (nested) arrays of generic types are supported.".to_string(), - ), + _ => Err("Unsupported field type".to_string()), } } diff --git a/crates/circuits/sha-macros/tests/arrays.rs b/crates/circuits/sha-macros/tests/arrays.rs new file mode 100644 index 0000000000..95564a9ce5 --- /dev/null +++ b/crates/circuits/sha-macros/tests/arrays.rs @@ -0,0 +1,19 @@ +use openvm_sha_air::{Sha256Config, ShaConfig}; +use openvm_sha_macros::ColsRef; + +#[derive(ColsRef)] +#[config(ShaConfig)] +struct ArrayTest { + a: T, + b: [T; 4], + c: [[T; 4]; 4], +} + +#[test] +fn arrays() { + let input = [1; 1 + 4 + 4 * 4]; + let test: ArrayTestRef = ArrayTestRef::from::(&input); + println!("{}", test.a); + println!("{}", test.b); + println!("{}", test.c); +} diff --git a/crates/circuits/sha-macros/tests/const-len-arrays.rs b/crates/circuits/sha-macros/tests/const-len-arrays.rs new file mode 100644 index 0000000000..671c65a88f --- /dev/null +++ b/crates/circuits/sha-macros/tests/const-len-arrays.rs @@ -0,0 +1,27 @@ +use openvm_sha_macros::ColsRef; + +const ONE: usize = 1; +const TWO: usize = 2; +const THREE: usize = 3; + +mod test_config; +use test_config::{TestConfig, TestConfigImpl}; + +#[derive(ColsRef)] +#[config(TestConfig)] +struct ConstLenArrayTest { + a: T, + b: [T; N], + c: [[T; ONE]; TWO], + d: [[[T; ONE]; TWO]; THREE], +} + +#[test] +fn const_len_arrays() { + let input = [1; 1 + TestConfigImpl::N * 2 + 1 * 2 * 3]; + let test: ConstLenArrayTestRef = ConstLenArrayTestRef::from::(&input); + println!("{}", test.a); + println!("{}", test.b); + println!("{}", test.c); + println!("{}", test.d); +} diff --git a/crates/circuits/sha-macros/tests/flags.rs b/crates/circuits/sha-macros/tests/flags.rs index 6da76c123d..9285c9f49d 100644 --- a/crates/circuits/sha-macros/tests/flags.rs +++ b/crates/circuits/sha-macros/tests/flags.rs @@ -3,6 +3,7 @@ use openvm_sha_macros::ColsRef; #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] 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 diff --git a/crates/circuits/sha-macros/tests/nested.rs b/crates/circuits/sha-macros/tests/nested.rs index 2425791706..53d89ed521 100644 --- a/crates/circuits/sha-macros/tests/nested.rs +++ b/crates/circuits/sha-macros/tests/nested.rs @@ -2,12 +2,14 @@ use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; #[derive(ColsRef)] +#[config(ShaConfig)] struct Test1Cols { pub a: T, pub nested: Test2Cols, } #[derive(ColsRef)] +#[config(ShaConfig)] struct Test2Cols { pub b: T, pub c: [T; WORD_BITS], diff --git a/crates/circuits/sha-macros/tests/plain.rs b/crates/circuits/sha-macros/tests/plain.rs new file mode 100644 index 0000000000..0591566084 --- /dev/null +++ b/crates/circuits/sha-macros/tests/plain.rs @@ -0,0 +1,53 @@ +use openvm_circuit_primitives_derive::AlignedBorrow; +use openvm_sha_macros::ColsRef; + +mod test_config; +use test_config::{TestConfig, TestConfigImpl}; + +#[derive(ColsRef)] +#[config(TestConfig)] +struct TestCols { + a: [T; N], + // Forces the field to be treated as a struct that derives AlignedBorrow. + // In particular, ignores the fact that it ends with `Cols` and doesn't + // expect a `PlainTestColsRef` type. + #[plain] + b: PlainCols, +} + +#[derive(Clone, Copy, Debug, AlignedBorrow)] +struct PlainCols { + a: T, + b: [T; 4], +} + +#[test] +fn plain() { + let input = [1; TestConfigImpl::N + 1 + 4]; + let test: TestColsRef = TestColsRef::from::(&input); + println!("{}", test.a); + println!("{:?}", test.b); +} + +#[test] +fn plain_mut() { + let mut input = [1; TestConfigImpl::N + 1 + 4]; + let mut test: TestColsRefMut = TestColsRefMut::from::(&mut input); + test.a[0] = 1; + test.b.a = 1; + test.b.b[0] = 1; + println!("{}", test.a); + println!("{:?}", test.b); +} + +#[test] +fn plain_from_mut() { + let mut input = [1; TestConfigImpl::N + 1 + 4]; + let mut test: TestColsRefMut = TestColsRefMut::from::(&mut input); + test.a[0] = 1; + test.b.a = 1; + test.b.b[0] = 1; + let test2: TestColsRef = TestColsRef::from_mut::(&mut test); + println!("{}", test2.a); + println!("{:?}", test2.b); +} diff --git a/crates/circuits/sha-macros/tests/simple.rs b/crates/circuits/sha-macros/tests/simple.rs index cf89118c58..4de63105a4 100644 --- a/crates/circuits/sha-macros/tests/simple.rs +++ b/crates/circuits/sha-macros/tests/simple.rs @@ -2,6 +2,7 @@ use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; #[derive(ColsRef)] +#[config(ShaConfig)] struct Test { a: T, b: [T; WORD_BITS], diff --git a/crates/circuits/sha-macros/tests/test_config.rs b/crates/circuits/sha-macros/tests/test_config.rs new file mode 100644 index 0000000000..aa3b592cbb --- /dev/null +++ b/crates/circuits/sha-macros/tests/test_config.rs @@ -0,0 +1,7 @@ +pub trait TestConfig { + const N: usize; +} +pub struct TestConfigImpl; +impl TestConfig for TestConfigImpl { + const N: usize = 4; +} diff --git a/crates/circuits/sha-macros/tests/work-vars.rs b/crates/circuits/sha-macros/tests/work-vars.rs index 6ca6d745cc..47b0547dd2 100644 --- a/crates/circuits/sha-macros/tests/work-vars.rs +++ b/crates/circuits/sha-macros/tests/work-vars.rs @@ -3,6 +3,7 @@ use openvm_sha_macros::ColsRef; #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaConfig)] pub struct ShaWorkVarsCols< T, const WORD_BITS: usize, From e5caa56aed1f15a5b015fbd569d231ee8623ea56 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Thu, 13 Feb 2025 16:57:31 -0500 Subject: [PATCH 10/27] Rename len method of ColsRef structs to width --- crates/circuits/sha-macros/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs index bccb6636a3..4c72378b5f 100644 --- a/crates/circuits/sha-macros/src/lib.rs +++ b/crates/circuits/sha-macros/src/lib.rs @@ -178,7 +178,8 @@ fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_mac } } - pub fn len() -> usize { + // returns number of cells in the struct (where each cell has type T) + pub const fn width() -> usize { 0 #( + #length_exprs )* } } @@ -319,10 +320,10 @@ fn get_const_cols_ref_fields( #const_cols_ref_type }, length_expr: quote! { - <#const_cols_ref_type>::len::() + <#const_cols_ref_type>::width::() }, prepare_subslice: quote! { - let #length_var = <#const_cols_ref_type>::len::(); + let #length_var = <#const_cols_ref_type>::width::(); let (#slice_var, slice) = slice.split_at(#length_var); let #slice_var = <#const_cols_ref_type>::from::(#slice_var); }, @@ -431,10 +432,10 @@ fn get_mut_cols_ref_fields( #mut_cols_ref_type }, length_expr: quote! { - <#mut_cols_ref_type>::len::() + <#mut_cols_ref_type>::width::() }, prepare_subslice: quote! { - let #length_var = <#mut_cols_ref_type>::len::(); + let #length_var = <#mut_cols_ref_type>::width::(); let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); let #slice_var = <#mut_cols_ref_type>::from::(#slice_var); }, From c45ce033c8218a3def1ca32d76c1025a2debd0cd Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 4 Apr 2025 11:46:40 -0400 Subject: [PATCH 11/27] Support SHA-512 --- Cargo.lock | 2 + Cargo.toml | 1 + crates/circuits/sha-air/Cargo.toml | 2 +- crates/circuits/sha-air/src/air.rs | 27 +- crates/circuits/sha-air/src/columns.rs | 5 +- crates/circuits/sha-air/src/config.rs | 39 +- crates/circuits/sha-air/src/tests.rs | 46 +- crates/circuits/sha-air/src/trace.rs | 22 +- crates/circuits/sha-macros/Cargo.toml | 1 + crates/circuits/sha-macros/src/lib.rs | 565 ++++++++++------- .../tests/{plain.rs => aligned_borrow.rs} | 8 +- crates/circuits/sha-macros/tests/arrays.rs | 82 ++- crates/sdk/src/config/global.rs | 16 +- .../system/memory/offline_checker/columns.rs | 4 + docs/specs/ISA.md | 7 +- docs/specs/RISCV.md | 5 +- docs/specs/transpiler.md | 3 +- extensions/sha256/circuit/Cargo.toml | 2 + extensions/sha256/circuit/src/extension.rs | 46 +- .../sha256/circuit/src/sha256_chip/air.rs | 548 ++++++++++------ .../sha256/circuit/src/sha256_chip/columns.rs | 102 ++- .../sha256/circuit/src/sha256_chip/config.rs | 75 +++ .../sha256/circuit/src/sha256_chip/mod.rs | 243 +++++--- .../sha256/circuit/src/sha256_chip/tests.rs | 89 ++- .../sha256/circuit/src/sha256_chip/trace.rs | 402 +++++++----- extensions/sha256/circuit/tmp.rs | 585 ++++++++++++++++++ extensions/sha256/guest/src/lib.rs | 51 +- extensions/sha256/tests/programs/Cargo.toml | 2 +- .../sha256/tests/programs/examples/sha.rs | 63 +- extensions/sha256/tests/src/lib.rs | 8 +- extensions/sha256/transpiler/src/lib.rs | 38 +- 31 files changed, 2237 insertions(+), 852 deletions(-) rename crates/circuits/sha-macros/tests/{plain.rs => aligned_borrow.rs} (91%) create mode 100644 extensions/sha256/circuit/src/sha256_chip/config.rs create mode 100644 extensions/sha256/circuit/tmp.rs diff --git a/Cargo.lock b/Cargo.lock index 76a195ac82..2d9306f3c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4404,6 +4404,7 @@ version = "1.0.0" dependencies = [ "derive-new 0.6.0", "derive_more 1.0.0", + "ndarray", "openvm-circuit", "openvm-circuit-derive", "openvm-circuit-primitives", @@ -4411,6 +4412,7 @@ dependencies = [ "openvm-instructions", "openvm-rv32im-circuit", "openvm-sha-air", + "openvm-sha-macros", "openvm-sha256-transpiler", "openvm-stark-backend", "openvm-stark-sdk", diff --git a/Cargo.toml b/Cargo.toml index eb2d023205..e71940a96d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -212,6 +212,7 @@ rrs-lib = "0.1.0" rand = { version = "0.8.5", default-features = false } hex = { version = "0.4.3", default-features = false } serde-big-array = "0.5.1" +ndarray = "0.16.1" # default-features = false for no_std for use in guest programs itertools = { version = "0.14.0", default-features = false } diff --git a/crates/circuits/sha-air/Cargo.toml b/crates/circuits/sha-air/Cargo.toml index 21524930cd..1b38c15184 100644 --- a/crates/circuits/sha-air/Cargo.toml +++ b/crates/circuits/sha-air/Cargo.toml @@ -10,7 +10,7 @@ openvm-stark-backend = { workspace = true } sha2 = { version = "0.10", features = ["compress"] } rand.workspace = true openvm-sha-macros = { workspace = true } -ndarray = "0.16" +ndarray.workspace = true [dev-dependencies] openvm-stark-sdk = { workspace = true } diff --git a/crates/circuits/sha-air/src/air.rs b/crates/circuits/sha-air/src/air.rs index 225a1c791c..8c8fb4411a 100644 --- a/crates/circuits/sha-air/src/air.rs +++ b/crates/circuits/sha-air/src/air.rs @@ -24,7 +24,7 @@ use crate::{ /// Expects the message to be padded to a multiple of C::BLOCK_WORDS * C::WORD_BITS bits #[derive(Clone, Debug)] -pub struct ShaAir { +pub struct Sha2Air { pub bitwise_lookup_bus: BitwiseOperationLookupBus, pub row_idx_encoder: Encoder, /// Internal bus for self-interactions in this AIR. @@ -32,7 +32,7 @@ pub struct ShaAir { _phantom: PhantomData, } -impl ShaAir { +impl Sha2Air { pub fn new(bitwise_lookup_bus: BitwiseOperationLookupBus, self_bus_idx: BusIndex) -> Self { Self { bitwise_lookup_bus, @@ -43,13 +43,13 @@ impl ShaAir { } } -impl BaseAir for ShaAir { +impl BaseAir for Sha2Air { fn width(&self) -> usize { max(C::ROUND_WIDTH, C::DIGEST_WIDTH) } } -impl SubAir for ShaAir { +impl SubAir for Sha2Air { /// The start column for the sub-air to use type AirContext<'a> = usize @@ -69,7 +69,7 @@ impl SubAir for ShaAir { } } -impl ShaAir { +impl Sha2Air { /// 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) { @@ -211,30 +211,35 @@ impl ShaAir { for j in 0..C::WORD_U16S { let work_var_limb = if i < C::ROUNDS_PER_ROW { compose::( - &local + local .work_vars .a .slice(s![C::ROUNDS_PER_ROW - 1 - i, j * 16..(j + 1) * 16]) - .as_slice().unwrap(), + .as_slice() + .unwrap(), 1, ) } else { compose::( - &local + local .work_vars .e .slice(s![C::ROUNDS_PER_ROW + 3 - i, j * 16..(j + 1) * 16]) - .as_slice().unwrap(), + .as_slice() + .unwrap(), 1, ) }; let final_hash_limb = compose::( - &next.final_hash.slice(s![i, j * 2..(j + 1) * 2]).as_slice().unwrap(), + 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) .assert_bool(carry.clone()); diff --git a/crates/circuits/sha-air/src/columns.rs b/crates/circuits/sha-air/src/columns.rs index 938cd2c3c7..784026d70b 100644 --- a/crates/circuits/sha-air/src/columns.rs +++ b/crates/circuits/sha-air/src/columns.rs @@ -122,12 +122,11 @@ pub struct ShaMessageHelperCols< #[config(ShaConfig)] 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 + /// A flag that indicates if the current row is among the first 4 rows of a block (the message rows) 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, @@ -150,7 +149,7 @@ impl, const ROW_VAR_CNT: usize> } } -impl<'a, O, T: Copy + core::ops::Add> ShaFlagsColsRef<'a, T> { +impl> ShaFlagsColsRef<'_, T> { pub fn is_not_padding_row(&self) -> O { *self.is_round_row + *self.is_digest_row } diff --git a/crates/circuits/sha-air/src/config.rs b/crates/circuits/sha-air/src/config.rs index 871ed866ab..986ca1480b 100644 --- a/crates/circuits/sha-air/src/config.rs +++ b/crates/circuits/sha-air/src/config.rs @@ -1,5 +1,7 @@ use std::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; +use crate::{ShaDigestColsRef, ShaRoundColsRef}; + pub trait ShaConfig: Send + Sync + Clone { type Word: 'static + Shr @@ -44,48 +46,25 @@ pub trait ShaConfig: Send + Sync + Clone { 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; + const ROUND_WIDTH: usize = ShaRoundColsRef::::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; + const DIGEST_WIDTH: usize = ShaDigestColsRef::::width::(); /// Width of the ShaCols const WIDTH: usize = if Self::ROUND_WIDTH > Self::DIGEST_WIDTH { Self::ROUND_WIDTH } else { Self::DIGEST_WIDTH }; -} + /// Number of cells used in each message row to store the message + const CELLS_PER_ROW: usize = Self::ROUNDS_PER_ROW * Self::WORD_U8S; -/// 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 { + /// To optimize the trace generation of invalid rows, we precompute those values. // 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]; + + /// We also store the SHA constants K and H fn get_k() -> &'static [Self::Word]; fn get_h() -> &'static [Self::Word]; } diff --git a/crates/circuits/sha-air/src/tests.rs b/crates/circuits/sha-air/src/tests.rs index a086d34747..479748f5ff 100644 --- a/crates/circuits/sha-air/src/tests.rs +++ b/crates/circuits/sha-air/src/tests.rs @@ -1,5 +1,5 @@ +use crate::{ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut}; use std::{borrow::BorrowMut, cmp::max, sync::Arc}; -use crate::{ShaDigestColsRefMut, ShaRoundColsRefMut, ShaRoundColsRef}; use openvm_circuit::arch::{ instructions::riscv::RV32_CELL_BITS, @@ -22,21 +22,19 @@ use openvm_stark_backend::{ use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; -use crate::{ - compose, small_sig0_field, Sha256Config, Sha512Config, ShaAir, ShaConfig, -}; +use crate::{compose, small_sig0_field, Sha256Config, Sha512Config, Sha2Air, ShaConfig}; // A wrapper AIR purely for testing purposes #[derive(Clone, Debug)] pub struct ShaTestAir { - pub sub_air: ShaAir, + pub sub_air: Sha2Air, } impl BaseAirWithPublicValues for ShaTestAir {} impl PartitionedBaseAir for ShaTestAir {} impl BaseAir for ShaTestAir { fn width(&self) -> usize { - as BaseAir>::width(&self.sub_air) + as BaseAir>::width(&self.sub_air) } } @@ -103,7 +101,7 @@ fn rand_sha_test() { .collect(); let chip = ShaTestChip { air: ShaTestAir { - sub_air: ShaAir::::new(bitwise_bus, SELF_BUS_IDX), + sub_air: Sha2Air::::new(bitwise_bus, SELF_BUS_IDX), }, bitwise_lookup_chip: bitwise_chip.clone(), records: random_records, @@ -125,14 +123,13 @@ fn rand_sha512_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> { +pub struct ShaTestBadFinalHashChip { pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, pub records: Vec<(Vec, bool)>, // length of inner vec should be C::BLOCK_U8S } -impl + 'static> Chip - for ShaTestBadFinalHashChip +impl Chip for ShaTestBadFinalHashChip where Val: PrimeField32, { @@ -170,12 +167,15 @@ where 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::, C>(&ShaRoundColsRef::from_mut::(&last_round_row), &mut last_digest_row); + generate_intermed_4::, C>( + &ShaRoundColsRef::from_mut::(&last_round_row), + &mut last_digest_row, + ); } } let non_padded_height = self.records.len() * C::ROWS_PER_BLOCK; - let width = as BaseAir>>::width(&self.air.sub_air); + 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 * C::ROWS_PER_BLOCK) @@ -190,7 +190,7 @@ where // Copy of private method in Sha256Air used for testing /// Puts the correct intermed_4 in the `next_row` -fn generate_intermed_4>( +fn generate_intermed_4( local_cols: &ShaRoundColsRef, next_cols: &mut ShaRoundColsRefMut, ) { @@ -209,10 +209,9 @@ fn generate_intermed_4>(), ] .concat(); - - + // length of inner vec is C::WORD_U16S - let w_limbs: Vec> = w + let w_limbs: Vec> = w .iter() .map(|x| { (0..C::WORD_U16S) @@ -231,7 +230,7 @@ fn generate_intermed_4> ChipUsageGetter for ShaTestBadFinalHashChip { +impl ChipUsageGetter for ShaTestBadFinalHashChip { fn air_name(&self) -> String { get_air_name(&self.air) } @@ -244,18 +243,25 @@ impl> ChipUsageGetter for ShaTestBa } } -fn test_sha_final_hash_constraints + 'static>() { +fn test_sha_final_hash_constraints() { 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(|_| ((0..C::BLOCK_U8S).map(|_| rng.gen::()).collect::>(), true)) + .map(|_| { + ( + (0..C::BLOCK_U8S) + .map(|_| rng.gen::()) + .collect::>(), + true, + ) + }) .collect(); let chip = ShaTestBadFinalHashChip { air: ShaTestAir { - sub_air: ShaAir::::new(bitwise_bus, SELF_BUS_IDX), + sub_air: Sha2Air::::new(bitwise_bus, SELF_BUS_IDX), }, bitwise_lookup_chip: bitwise_chip.clone(), records: random_records, diff --git a/crates/circuits/sha-air/src/trace.rs b/crates/circuits/sha-air/src/trace.rs index 2886ca72df..f462864029 100644 --- a/crates/circuits/sha-air/src/trace.rs +++ b/crates/circuits/sha-air/src/trace.rs @@ -10,7 +10,7 @@ use openvm_stark_backend::{ use sha2::{compress256, compress512, digest::generic_array::GenericArray}; use super::{ - air::ShaAir, big_sig0_field, big_sig1_field, ch_field, compose, get_flag_pt_array, maj_field, + air::Sha2Air, big_sig0_field, big_sig1_field, ch_field, compose, get_flag_pt_array, maj_field, small_sig0_field, small_sig1_field, ShaRoundColsRefMut, }; use crate::{ @@ -22,7 +22,7 @@ use crate::{ /// 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 { +impl Sha2Air { /// 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: &[C::Word], input: Vec) -> Vec { @@ -63,14 +63,14 @@ impl ShaAir { is_last_block: bool, global_block_idx: u32, local_block_idx: u32, - buffer_vals: Vec<&[F]>, + buffer_vals: Vec>, ) { #[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!(buffer_vals.iter().all(|x| x.len() == C::CELLS_PER_ROW)); 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()); @@ -122,9 +122,7 @@ impl ShaAir { .carry_or_buffer .row_mut(j) .iter_mut() - .zip( - (0..C::WORD_U16S).map(|k| buffer_vals[i][j * C::WORD_U16S * 2 + k]), - ) + .zip((0..C::WORD_U8S).map(|k| buffer_vals[i][j * C::WORD_U8S + k])) .for_each(|(x, y)| *x = y); } } @@ -750,7 +748,7 @@ impl ShaAir { /// `records` consists of pairs of `(input_block, is_last_block)`. pub fn generate_trace( - sub_air: &ShaAir, + sub_air: &Sha2Air, bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, records: Vec<(Vec, bool)>, ) -> RowMajorMatrix { @@ -760,7 +758,7 @@ pub fn generate_trace( let non_padded_height = records.len() * C::ROWS_PER_BLOCK; let height = next_power_of_two_or_zero(non_padded_height); - let width = as BaseAir>::width(sub_air); + let width = as BaseAir>::width(sub_air); let mut values = F::zero_vec(height * width); struct BlockContext { @@ -788,7 +786,7 @@ pub fn generate_trace( prev_hash = C::get_h().to_vec(); } else { local_block_idx += 1; - prev_hash = ShaAir::::get_block_hash(&prev_hash, input); + prev_hash = Sha2Air::::get_block_hash(&prev_hash, input); } } // first pass @@ -812,8 +810,8 @@ pub fn generate_trace( ) }) .collect::>(); - let empty_buffer = vec![F::ZERO; C::BUFFER_SIZE]; - let buffer_vals = vec![empty_buffer.as_slice(); C::MESSAGE_ROWS]; + let empty_buffer = vec![F::ZERO; C::CELLS_PER_ROW]; + let buffer_vals = vec![empty_buffer.clone(); C::MESSAGE_ROWS]; sub_air.generate_block_trace( block, width, diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml index af434f1c1a..c926edf248 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/sha-macros/Cargo.toml @@ -11,6 +11,7 @@ syn = { version = "2.0", features = ["full", "extra-traits"] } quote = "1.0" itertools = "0.14" proc-macro2 = "1.0" +ndarray = "0.16" [dev-dependencies] openvm-sha-air = { workspace = true } diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs index 4c72378b5f..ecb5141c66 100644 --- a/crates/circuits/sha-macros/src/lib.rs +++ b/crates/circuits/sha-macros/src/lib.rs @@ -5,7 +5,7 @@ use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::{parse_macro_input, parse_quote, DeriveInput}; -#[proc_macro_derive(ColsRef, attributes(plain, config))] +#[proc_macro_derive(ColsRef, attributes(aligned_borrow, config, plain_array))] pub fn cols_ref(input: TokenStream) -> TokenStream { let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput); @@ -166,6 +166,7 @@ fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_mac quote! { #clone_impl + #[derive(Debug)] #vis struct #name <'a, #generic_type> { #( pub #idents: #field_types ),* } @@ -178,6 +179,7 @@ fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_mac } } + // TODO: make this return the size in bytes (to support fields of constant size) // returns number of cells in the struct (where each cell has type T) pub const fn width() -> usize { 0 #( + #length_exprs )* @@ -200,49 +202,39 @@ fn make_from_mut( 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(); - if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) { + let derives_aligned_borrow = f + .attrs + .iter() + .any(|attr| attr.path().is_ident("aligned_borrow")); + + let is_array = matches!(f.ty, syn::Type::Array(_)); + + if is_array { + Ok(quote! { + other.#ident.view() + }) + } else if derives_aligned_borrow { Ok(quote! { other.#ident }) + } else if is_columns_struct(&f.ty) { + // 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 if is_generic_type(&f.ty, &generic_type) { + Ok(quote! { + &other.#ident + }) } else { - 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)), - } + panic!("Unsupported field type: {:?}", f.ty); } }) .collect::, String>>()?; @@ -258,6 +250,7 @@ fn make_from_mut( }; Ok(parse_quote! { + // lifetime 'b is used in from_mut to allow more flexible lifetime of return value impl<'b, #generic_type> #name<'b, #generic_type> { pub fn from_mut<'a, C: #config>(other: &'b #mut_struct_type) -> Self { @@ -291,10 +284,111 @@ fn get_const_cols_ref_fields( let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); - if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) { - // treat the field as a struct that derives AlignedBorrow + let derives_aligned_borrow = f + .attrs + .iter() + .any(|attr| attr.path().is_ident("aligned_borrow")); + + let has_plain_array_attribute = f.attrs.iter().any(|attr| attr.path().is_ident("array")); + let is_array = matches!(f.ty, syn::Type::Array(_)); + + if has_plain_array_attribute && !is_array { + panic!("field marked with `plain_array` attribute must be an array"); + } + + if is_array { + let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); + debug_assert!( + !dims.is_empty(), + "Array field must have at least one dimension" + ); + + let ndarray_ident: syn::Ident = format_ident!("ArrayView{}", dims.len()); + let ndarray_type: syn::Type = parse_quote! { + ndarray::#ndarray_ident<'a, #elem_type> + }; + + // dimensions of the array in terms of number of cells + let dim_exprs = dims + .iter() + .map(|d| match d { + // need to prepend C:: for const generic array dimensions + Dimension::ConstGeneric(expr) => quote! { C::#expr }, + Dimension::Other(expr) => quote! { #expr }, + }) + .collect_vec(); + + if has_plain_array_attribute { + Err("unsupported currently".to_string()) + /* + debug_assert!( + dims.len() == 1, + "field marked with `plain_array` attribute must be a 1D array" + ); + + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + + Ok(FieldInfo { + ty: parse_quote! { + & #f.ty + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var = #slice_var.try_into().unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + */ + } else if derives_aligned_borrow { + let length_expr = quote! { + <#elem_type>::width() #(* #dim_exprs)* + }; + + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var: &[#elem_type] = unsafe { &*(#slice_var as *const [T] as *const [#elem_type]) }; + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else if is_columns_struct(&elem_type) { + panic!("Arrays of columns structs are currently not supported"); + } else if is_generic_type(&elem_type, generic_type) { + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else { + panic!("Unsupported field type: {:?}", f.ty); + } + } else if derives_aligned_borrow { + // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) let f_ty = &f.ty; - return Ok(FieldInfo { + Ok(FieldInfo { ty: parse_quote! { &'a #f_ty }, @@ -311,11 +405,10 @@ fn get_const_cols_ref_fields( #slice_var.borrow() } }, - }); - } - - match get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }) { - Some(const_cols_ref_type) => Ok(FieldInfo { + }) + } else if is_columns_struct(&f.ty) { + let const_cols_ref_type = get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }); + Ok(FieldInfo { ty: parse_quote! { #const_cols_ref_type }, @@ -328,69 +421,27 @@ fn get_const_cols_ref_fields( let #slice_var = <#const_cols_ref_type>::from::(#slice_var); }, initializer: quote! { - #slice_var + #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, const_generics).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> - }; - let dim_exprs = dims - .iter() - .map(|d| match d { - // need to prepend C:: for const generic array dimensions - Dimension::ConstGeneric(expr) => quote! { C::#expr }, - Dimension::Other(expr) => quote! { #expr }, - }) - .collect_vec(); - let length_expr = quote! { - 1 #(* #dim_exprs)* - }; - - Ok(FieldInfo { - ty: parse_quote! { - #ndarray_type - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at(#length_expr); - let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - } - } + }) + } else if is_generic_type(&f.ty, generic_type) { + 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 { + panic!("Unsupported field type: {:?}", f.ty); } } @@ -403,10 +454,80 @@ fn get_mut_cols_ref_fields( let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); - if f.attrs.iter().any(|attr| attr.path().is_ident("plain")) { - // treat the field as a struct that derives AlignedBorrow + let derives_aligned_borrow = f + .attrs + .iter() + .any(|attr| attr.path().is_ident("aligned_borrow")); + + let is_array = matches!(f.ty, syn::Type::Array(_)); + + if is_array { + let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); + debug_assert!( + !dims.is_empty(), + "Array field must have at least one dimension" + ); + + let ndarray_ident: syn::Ident = format_ident!("ArrayViewMut{}", dims.len()); + let ndarray_type: syn::Type = parse_quote! { + ndarray::#ndarray_ident<'a, #elem_type> + }; + + // dimensions of the array in terms of number of cells + let dim_exprs = dims + .iter() + .map(|d| match d { + // need to prepend C:: for const generic array dimensions + Dimension::ConstGeneric(expr) => quote! { C::#expr }, + Dimension::Other(expr) => quote! { #expr }, + }) + .collect_vec(); + + if derives_aligned_borrow { + let length_expr = quote! { + <#elem_type>::width() #(* #dim_exprs)* + }; + + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at_mut (#length_expr); + let #slice_var: &mut [#elem_type] = unsafe { &mut *(#slice_var as *mut [T] as *mut [#elem_type]) }; + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else if is_columns_struct(&elem_type) { + panic!("Arrays of columns structs are currently not supported"); + } else if is_generic_type(&elem_type, generic_type) { + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at_mut(#length_expr); + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else { + panic!("Unsupported field type: {:?}", f.ty); + } + } else if derives_aligned_borrow { + // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) let f_ty = &f.ty; - return Ok(FieldInfo { + Ok(FieldInfo { ty: parse_quote! { &'a mut #f_ty }, @@ -415,7 +536,7 @@ fn get_mut_cols_ref_fields( }, prepare_subslice: quote! { let #length_var = <#f_ty>::width(); - let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); + let (#slice_var, slice) = slice.split_at_mut(#length_var); }, initializer: quote! { { @@ -423,11 +544,10 @@ fn get_mut_cols_ref_fields( #slice_var.borrow_mut() } }, - }); - } - - match get_mut_cols_ref_type(&f.ty, generic_type) { - Some(mut_cols_ref_type) => Ok(FieldInfo { + }) + } else if is_columns_struct(&f.ty) { + let mut_cols_ref_type = get_mut_cols_ref_type(&f.ty, generic_type); + Ok(FieldInfo { ty: parse_quote! { #mut_cols_ref_type }, @@ -436,72 +556,45 @@ fn get_mut_cols_ref_fields( }, prepare_subslice: quote! { let #length_var = <#mut_cols_ref_type>::width::(); - let (mut #slice_var, mut slice) = slice.split_at_mut(#length_var); + let (#slice_var, 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, const_generics).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> - }; - let dim_exprs = dims - .iter() - .map(|d| match d { - // need to prepend C:: for const generic array dimensions - Dimension::ConstGeneric(expr) => quote! { C::#expr }, - Dimension::Other(expr) => quote! { #expr }, - }) - .collect_vec(); - let length_expr = quote! { - 1 #(* #dim_exprs)* - }; - Ok(FieldInfo { - ty: parse_quote! { - #ndarray_type - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (mut #slice_var, mut slice) = slice.split_at_mut(#length_expr); - let mut #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - } - } + }) + } else if is_generic_type(&f.ty, generic_type) { + Ok(FieldInfo { + ty: parse_quote! { + &'a mut #generic_type + }, + length_expr: quote! { + 1 + }, + prepare_subslice: quote! { + let #length_var = 1; + let (#slice_var, slice) = slice.split_at_mut(#length_var); + }, + initializer: quote! { + &mut #slice_var[0] + }, + }) + } else { + panic!("Unsupported field type: {:?}", f.ty); + } +} + +fn is_columns_struct(ty: &syn::Type) -> bool { + if let syn::Type::Path(type_path) = ty { + type_path + .path + .segments + .iter() + .last() + .map(|s| s.ident.to_string().ends_with("Cols")) + .unwrap_or(false) + } else { + false } } @@ -511,41 +604,71 @@ fn get_const_cols_ref_type( ty: &syn::Type, generic_type: &syn::TypeParam, lifetime: syn::Lifetime, -) -> Option { +) -> syn::TypePath { + if !is_columns_struct(ty) { + panic!("Expected a columns struct, got {:?}", ty); + } + 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 - } - }) + let s = type_path.path.segments.iter().last().unwrap(); + 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> + }; + const_cols_ref_type + } else { + panic!("is_columns_struct returned true for type {:?} but the last segment is not a columns struct", ty); + } } else { - None + panic!( + "is_columns_struct returned true but the type {:?} is not a path", + ty + ); } } // 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 { +fn get_mut_cols_ref_type(ty: &syn::Type, generic_type: &syn::TypeParam) -> syn::TypePath { + if !is_columns_struct(ty) { + panic!("Expected a columns struct, got {:?}", ty); + } + 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 - } - }) + let s = type_path.path.segments.iter().last().unwrap(); + 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> + }; + mut_cols_ref_type + } else { + panic!("is_columns_struct returned true for type {:?} but the last segment is not a columns struct", ty); + } } else { - None + panic!( + "is_columns_struct returned true but the type {:?} is not a path", + ty + ); + } +} + +fn is_generic_type(ty: &syn::Type, generic_type: &syn::TypeParam) -> bool { + if let syn::Type::Path(type_path) = ty { + if type_path.path.segments.len() == 1 { + type_path + .path + .segments + .iter() + .last() + .map(|s| s.ident == generic_type.ident) + .unwrap_or(false) + } else { + false + } + } else { + false } } @@ -554,14 +677,38 @@ enum Dimension { ConstGeneric(syn::Expr), Other(syn::Expr), } -fn get_dims(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Result, String> { - get_dims_impl(ty, const_generics).map(|dims| dims.into_iter().rev().collect()) + +// Describes a nested array +struct ArrayInfo { + dims: Vec, + elem_type: syn::Type, +} + +fn get_array_info(ty: &syn::Type, const_generics: &[&syn::Ident]) -> ArrayInfo { + let dims = get_dims(ty, const_generics); + let elem_type = get_elem_type(ty); + ArrayInfo { dims, elem_type } +} + +fn get_elem_type(ty: &syn::Type) -> syn::Type { + match ty { + syn::Type::Array(array) => get_elem_type(array.elem.as_ref()), + syn::Type::Path(_) => ty.clone(), + _ => panic!("Unsupported type: {:?}", ty), + } +} + +fn get_dims(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { + get_dims_impl(ty, const_generics) + .into_iter() + .rev() + .collect() } -fn get_dims_impl(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Result, String> { +fn get_dims_impl(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { match ty { syn::Type::Array(array) => { - let mut dims = get_dims_impl(array.elem.as_ref(), const_generics)?; + let mut dims = get_dims_impl(array.elem.as_ref(), const_generics); match &array.len { syn::Expr::Path(syn::ExprPath { path, .. }) => { let len_ident = path.get_ident(); @@ -572,11 +719,11 @@ fn get_dims_impl(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Result dims.push(Dimension::Other(expr_lit.clone().into())), - _ => return Err("Unsupported array length type".to_string()), + _ => panic!("Unsupported array length type"), } - Ok(dims) + dims } - syn::Type::Path(_) => Ok(Vec::new()), - _ => Err("Unsupported field type".to_string()), + syn::Type::Path(_) => Vec::new(), + _ => panic!("Unsupported field type"), } } diff --git a/crates/circuits/sha-macros/tests/plain.rs b/crates/circuits/sha-macros/tests/aligned_borrow.rs similarity index 91% rename from crates/circuits/sha-macros/tests/plain.rs rename to crates/circuits/sha-macros/tests/aligned_borrow.rs index 0591566084..65fdab5e49 100644 --- a/crates/circuits/sha-macros/tests/plain.rs +++ b/crates/circuits/sha-macros/tests/aligned_borrow.rs @@ -10,13 +10,13 @@ struct TestCols { a: [T; N], // Forces the field to be treated as a struct that derives AlignedBorrow. // In particular, ignores the fact that it ends with `Cols` and doesn't - // expect a `PlainTestColsRef` type. - #[plain] - b: PlainCols, + // expect a `AlignedBorrowColsRef` type. + #[aligned_borrow] + b: AlignedBorrowCols, } #[derive(Clone, Copy, Debug, AlignedBorrow)] -struct PlainCols { +struct AlignedBorrowCols { a: T, b: [T; 4], } diff --git a/crates/circuits/sha-macros/tests/arrays.rs b/crates/circuits/sha-macros/tests/arrays.rs index 95564a9ce5..32a0a4c4d8 100644 --- a/crates/circuits/sha-macros/tests/arrays.rs +++ b/crates/circuits/sha-macros/tests/arrays.rs @@ -1,19 +1,83 @@ -use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; +mod test_config; +use test_config::{TestConfig, TestConfigImpl}; + #[derive(ColsRef)] -#[config(ShaConfig)] -struct ArrayTest { +#[config(TestConfig)] +struct ArrayTest { a: T, - b: [T; 4], - c: [[T; 4]; 4], + b: [T; N], + c: [[T; 4]; N], } #[test] fn arrays() { - let input = [1; 1 + 4 + 4 * 4]; - let test: ArrayTestRef = ArrayTestRef::from::(&input); + let input = [1; 1 + TestConfigImpl::N + 4 * TestConfigImpl::N]; + let test: ArrayTestRef = ArrayTestRef::from::(&input); println!("{}", test.a); - println!("{}", test.b); - println!("{}", test.c); + println!("{:?}", test.b); + println!("{:?}", test.c); +} + +/* +#[derive(Clone)] +struct ArrayTestRef<'a, T> { + pub a: &'a T, + pub b: ndarray::ArrayView1<'a, T>, + pub c: ndarray::ArrayView2<'a, T>, +} + +impl<'a, T> ArrayTestRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let a_length = 1; + let (a_slice, slice) = slice.split_at(a_length); + let (b_slice, slice) = slice.split_at(1 * C::N); + let b_slice = ndarray::ArrayView1::from_shape((C::N), b_slice).unwrap(); + let (c_slice, slice) = slice.split_at(1 * C::N * 4); + let c_slice = ndarray::ArrayView2::from_shape((C::N, 4), c_slice).unwrap(); + Self { + a: &a_slice[0], + b: b_slice, + c: c_slice, + } + } + pub const fn width() -> usize { + 0 + 1 + 1 * C::N + 1 * C::N * 4 + } +} + +impl<'b, T> ArrayTestRef<'b, T> { + pub fn from_mut<'a, C: TestConfig>(other: &'b ArrayTestRefMut<'a, T>) -> Self { + Self { + a: &other.a, + b: other.b.view(), + c: other.c.view(), + } + } +} +struct ArrayTestRefMut<'a, T> { + pub a: &'a mut T, + pub b: ndarray::ArrayViewMut1<'a, T>, + pub c: ndarray::ArrayViewMut2<'a, T>, +} + +impl<'a, T> ArrayTestRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let a_length = 1; + let (mut a_slice, mut slice) = slice.split_at_mut(a_length); + let (mut b_slice, mut slice) = slice.split_at_mut(1 * C::N); + let b_slice = ndarray::ArrayViewMut1::from_shape((C::N), b_slice).unwrap(); + let (mut c_slice, mut slice) = slice.split_at_mut(1 * C::N * 4); + let c_slice = ndarray::ArrayViewMut2::from_shape((C::N, 4), c_slice).unwrap(); + Self { + a: &mut a_slice[0], + b: b_slice, + c: c_slice, + } + } + pub const fn width() -> usize { + 0 + 1 + 1 * C::N + 1 * C::N * 4 + } } +*/ diff --git a/crates/sdk/src/config/global.rs b/crates/sdk/src/config/global.rs index 532c9b8d1c..92cba17d6a 100644 --- a/crates/sdk/src/config/global.rs +++ b/crates/sdk/src/config/global.rs @@ -35,8 +35,8 @@ use openvm_rv32im_circuit::{ use openvm_rv32im_transpiler::{ Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension, }; -use openvm_sha256_circuit::{Sha256, Sha256Executor, Sha256Periphery}; -use openvm_sha256_transpiler::Sha256TranspilerExtension; +use openvm_sha256_circuit::{Sha2, Sha2Executor, Sha2Periphery}; +use openvm_sha256_transpiler::Sha2TranspilerExtension; use openvm_stark_backend::p3_field::PrimeField32; use openvm_transpiler::transpiler::Transpiler; use serde::{Deserialize, Serialize}; @@ -74,7 +74,7 @@ pub enum SdkVmConfigExecutor { #[any_enum] Keccak(Keccak256Executor), #[any_enum] - Sha256(Sha256Executor), + Sha2(Sha2Executor), #[any_enum] Native(NativeExecutor), #[any_enum] @@ -104,7 +104,7 @@ pub enum SdkVmConfigPeriphery { #[any_enum] Keccak(Keccak256Periphery), #[any_enum] - Sha256(Sha256Periphery), + Sha2(Sha2Periphery), #[any_enum] Native(NativePeriphery), #[any_enum] @@ -136,7 +136,7 @@ impl SdkVmConfig { transpiler = transpiler.with_extension(Keccak256TranspilerExtension); } if self.sha256.is_some() { - transpiler = transpiler.with_extension(Sha256TranspilerExtension); + transpiler = transpiler.with_extension(Sha2TranspilerExtension); } if self.rv32m.is_some() { transpiler = transpiler.with_extension(Rv32MTranspilerExtension); @@ -187,7 +187,7 @@ impl VmConfig for SdkVmConfig { complex = complex.extend(&Keccak256)?; } if self.sha256.is_some() { - complex = complex.extend(&Sha256)?; + complex = complex.extend(&Sha2)?; } if self.native.is_some() { complex = complex.extend(&Native)?; @@ -275,8 +275,8 @@ impl From for UnitStruct { } } -impl From for UnitStruct { - fn from(_: Sha256) -> Self { +impl From for UnitStruct { + fn from(_: Sha2) -> Self { UnitStruct {} } } diff --git a/crates/vm/src/system/memory/offline_checker/columns.rs b/crates/vm/src/system/memory/offline_checker/columns.rs index 5ba1b8da6c..4b4372dbed 100644 --- a/crates/vm/src/system/memory/offline_checker/columns.rs +++ b/crates/vm/src/system/memory/offline_checker/columns.rs @@ -19,6 +19,10 @@ pub struct MemoryBaseAuxCols { pub(in crate::system::memory) timestamp_lt_aux: LessThanAuxCols, } +pub trait MemoryWriteAuxColsConfig { + const N: usize; +} + #[repr(C)] #[derive(Clone, Copy, Debug, AlignedBorrow)] pub struct MemoryWriteAuxCols { diff --git a/docs/specs/ISA.md b/docs/specs/ISA.md index 1bc3d0c4a0..7cdb69c0f7 100644 --- a/docs/specs/ISA.md +++ b/docs/specs/ISA.md @@ -6,7 +6,7 @@ This specification describes the overall architecture and default VM extensions - [RV32IM](#rv32im-extension): An extension supporting the 32-bit RISC-V ISA with multiplication. - [Native](#native-extension): An extension supporting native field arithmetic for proof recursion and aggregation. - [Keccak-256](#keccak-extension): An extension implementing the Keccak-256 hash function compatibly with RISC-V memory. -- [SHA2-256](#sha2-256-extension): An extension implementing the SHA2-256 hash function compatibly with RISC-V memory. +- [SHA2](#sha2-extension): An extension implementing the SHA2-256 and SHA2-512 hash functions compatibly with RISC-V memory. - [BigInt](#bigint-extension): An extension supporting 256-bit signed and unsigned integer arithmetic, including multiplication. This extension respects the RISC-V memory format. - [Algebra](#algebra-extension): An extension supporting modular arithmetic over arbitrary fields and their complex @@ -538,14 +538,15 @@ all memory cells are constrained to be bytes. | -------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- | | KECCAK256_RV32 | `a,b,c,1,2` | `[r32{0}(a):32]_2 = keccak256([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Performs memory accesses with block size `4`. | -### SHA2-256 Extension +### SHA2 Extension -The SHA2-256 extension supports the SHA2-256 hash function. The extension operates on address spaces `1` and `2`, +The SHA2 extension supports the SHA2-256 and SHA2-512 hash functions. The extension operates on address spaces `1` and `2`, meaning all memory cells are constrained to be bytes. | Name | Operands | Description | | ----------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | SHA256_RV32 | `a,b,c,1,2` | `[r32{0}(a):32]_2 = sha256([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Does the necessary padding. Performs memory reads with block size `16` and writes with block size `32`. | +| SHA512_RV32 | `a,b,c,1,2` | `[r32{0}(a):64]_2 = sha512([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Does the necessary padding. Performs memory reads with block size `16` and writes with block size `64`. | ### BigInt Extension diff --git a/docs/specs/RISCV.md b/docs/specs/RISCV.md index 7948272c66..113ba0d731 100644 --- a/docs/specs/RISCV.md +++ b/docs/specs/RISCV.md @@ -5,7 +5,7 @@ The default VM extensions that support transpilation are: - [RV32IM](#rv32im-extension): An extension supporting the 32-bit RISC-V ISA with multiplication. - [Keccak-256](#keccak-extension): An extension implementing the Keccak-256 hash function compatibly with RISC-V memory. -- [SHA2-256](#sha2-256-extension): An extension implementing the SHA2-256 hash function compatibly with RISC-V memory. +- [SHA2](#sha2-extension): An extension implementing the SHA2-256 and SHA2-512 hash functions compatibly with RISC-V memory. - [BigInt](#bigint-extension): An extension supporting 256-bit signed and unsigned integer arithmetic, including multiplication. This extension respects the RISC-V memory format. - [Algebra](#algebra-extension): An extension supporting modular arithmetic over arbitrary fields and their complex field extensions. This extension respects the RISC-V memory format. - [Elliptic curve](#elliptic-curve-extension): An extension for elliptic curve operations over Weierstrass curves, including addition and doubling. This can be used to implement multi-scalar multiplication and ECDSA scalar multiplication. This extension respects the RISC-V memory format. @@ -78,11 +78,12 @@ the guest must take care to validate all data and account for behavior in cases | ----------- | --- | ----------- | ------ | ------ | ------------------------------------------- | | keccak256 | R | 0001011 | 100 | 0x0 | `[rd:32]_2 = keccak256([rs1..rs1 + rs2]_2)` | -## SHA2-256 Extension +## SHA2 Extension | RISC-V Inst | FMT | opcode[6:0] | funct3 | funct7 | RISC-V description and notes | | ----------- | --- | ----------- | ------ | ------ | ---------------------------------------- | | sha256 | R | 0001011 | 100 | 0x1 | `[rd:32]_2 = sha256([rs1..rs1 + rs2]_2)` | +| sha512 | R | 0001011 | 100 | 0x2 | `[rd:32]_2 = sha512([rs1..rs1 + rs2]_2)` | ## BigInt Extension diff --git a/docs/specs/transpiler.md b/docs/specs/transpiler.md index a8b94ef2b0..1e5da4be4b 100644 --- a/docs/specs/transpiler.md +++ b/docs/specs/transpiler.md @@ -151,11 +151,12 @@ Each VM extension's behavior is specified below. | ----------- | -------------------------------------------------- | | keccak256 | KECCAK256_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | -### SHA2-256 Extension +### SHA2 Extension | RISC-V Inst | OpenVM Instruction | | ----------- | ----------------------------------------------- | | sha256 | SHA256_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | +| sha512 | SHA512_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | ### BigInt Extension diff --git a/extensions/sha256/circuit/Cargo.toml b/extensions/sha256/circuit/Cargo.toml index 388cdf17ad..5a45bc4d0c 100644 --- a/extensions/sha256/circuit/Cargo.toml +++ b/extensions/sha256/circuit/Cargo.toml @@ -16,6 +16,7 @@ openvm-instructions = { workspace = true } openvm-sha256-transpiler = { workspace = true } openvm-rv32im-circuit = { workspace = true } openvm-sha-air = { workspace = true } +openvm-sha-macros = { workspace = true } derive-new.workspace = true derive_more = { workspace = true, features = ["from"] } @@ -23,6 +24,7 @@ rand.workspace = true serde.workspace = true sha2 = { version = "0.10", default-features = false } strum = { workspace = true } +ndarray.workspace = true [dev-dependencies] openvm-stark-sdk = { workspace = true } diff --git a/extensions/sha256/circuit/src/extension.rs b/extensions/sha256/circuit/src/extension.rs index 76a6c1ec0c..abd40002e2 100644 --- a/extensions/sha256/circuit/src/extension.rs +++ b/extensions/sha256/circuit/src/extension.rs @@ -13,15 +13,15 @@ use openvm_rv32im_circuit::{ Rv32I, Rv32IExecutor, Rv32IPeriphery, Rv32Io, Rv32IoExecutor, Rv32IoPeriphery, Rv32M, Rv32MExecutor, Rv32MPeriphery, }; -use openvm_sha256_transpiler::Rv32Sha256Opcode; +use openvm_sha256_transpiler::Rv32Sha2Opcode; +use openvm_sha_air::{Sha256Config, Sha512Config}; use openvm_stark_backend::p3_field::PrimeField32; use serde::{Deserialize, Serialize}; -use strum::IntoEnumIterator; use crate::*; #[derive(Clone, Debug, VmConfig, derive_new::new, Serialize, Deserialize)] -pub struct Sha256Rv32Config { +pub struct Sha2Rv32Config { #[system] pub system: SystemConfig, #[extension] @@ -31,38 +31,39 @@ pub struct Sha256Rv32Config { #[extension] pub io: Rv32Io, #[extension] - pub sha256: Sha256, + pub sha2: Sha2, } -impl Default for Sha256Rv32Config { +impl Default for Sha2Rv32Config { fn default() -> Self { Self { system: SystemConfig::default().with_continuations(), rv32i: Rv32I, rv32m: Rv32M::default(), io: Rv32Io, - sha256: Sha256, + sha2: Sha2, } } } #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] -pub struct Sha256; +pub struct Sha2; #[derive(ChipUsageGetter, Chip, InstructionExecutor, From, AnyEnum)] -pub enum Sha256Executor { - Sha256(Sha256VmChip), +pub enum Sha2Executor { + Sha256(Sha2VmChip), + Sha512(Sha2VmChip), } #[derive(From, ChipUsageGetter, Chip, AnyEnum)] -pub enum Sha256Periphery { +pub enum Sha2Periphery { BitwiseOperationLookup(SharedBitwiseOperationLookupChip<8>), Phantom(PhantomChip), } -impl VmExtension for Sha256 { - type Executor = Sha256Executor; - type Periphery = Sha256Periphery; +impl VmExtension for Sha2 { + type Executor = Sha2Executor; + type Periphery = Sha2Periphery; fn build( &self, @@ -81,18 +82,25 @@ impl VmExtension for Sha256 { chip }; - let sha256_chip = Sha256VmChip::new( + let sha256_chip = Sha2VmChip::::new( + builder.system_port(), + builder.system_config().memory_config.pointer_max_bits, + bitwise_lu_chip.clone(), + builder.new_bus_idx(), + Rv32Sha2Opcode::CLASS_OFFSET, + builder.system_base().offline_memory(), + ); + inventory.add_executor(sha256_chip, vec![Rv32Sha2Opcode::SHA256.global_opcode()])?; + + let sha512_chip = Sha2VmChip::::new( builder.system_port(), builder.system_config().memory_config.pointer_max_bits, bitwise_lu_chip, builder.new_bus_idx(), - Rv32Sha256Opcode::CLASS_OFFSET, + Rv32Sha2Opcode::CLASS_OFFSET, builder.system_base().offline_memory(), ); - inventory.add_executor( - sha256_chip, - Rv32Sha256Opcode::iter().map(|x| x.global_opcode()), - )?; + inventory.add_executor(sha512_chip, vec![Rv32Sha2Opcode::SHA512.global_opcode()])?; Ok(inventory) } diff --git a/extensions/sha256/circuit/src/sha256_chip/air.rs b/extensions/sha256/circuit/src/sha256_chip/air.rs index 218bbe5603..ddd7528eb3 100644 --- a/extensions/sha256/circuit/src/sha256_chip/air.rs +++ b/extensions/sha256/circuit/src/sha256_chip/air.rs @@ -1,8 +1,11 @@ -use std::{array, borrow::Borrow, cmp::min}; +use std::cmp::min; use openvm_circuit::{ arch::ExecutionBridge, - system::memory::{offline_checker::MemoryBridge, MemoryAddress}, + system::memory::{ + offline_checker::{MemoryBridge, MemoryWriteAuxCols}, + MemoryAddress, + }, }; use openvm_circuit_primitives::{ bitwise_op_lookup::BitwiseOperationLookupBus, encoder::Encoder, utils::not, SubAir, @@ -11,11 +14,7 @@ use openvm_instructions::{ riscv::{RV32_CELL_BITS, RV32_MEMORY_AS, RV32_REGISTER_AS, RV32_REGISTER_NUM_LIMBS}, LocalOpcode, }; -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_sha_air::{compose, Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{ interaction::InteractionBuilder, p3_air::{Air, AirBuilder, BaseAir}, @@ -24,15 +23,12 @@ use openvm_stark_backend::{ rap::{BaseAirWithPublicValues, PartitionedBaseAir}, }; -use super::{ - Sha256VmDigestCols, Sha256VmRoundCols, SHA256VM_CONTROL_WIDTH, SHA256VM_DIGEST_WIDTH, - SHA256VM_ROUND_WIDTH, SHA256VM_WIDTH, SHA256_READ_SIZE, -}; +use super::{Sha2Variant, ShaChipConfig, ShaVmDigestColsRef, ShaVmRoundColsRef}; /// Sha256VmAir does all constraints related to message padding and /// the Sha256Air subair constrains the actual hash #[derive(Clone, Debug, derive_new::new)] -pub struct Sha256VmAir { +pub struct Sha2VmAir { pub execution_bridge: ExecutionBridge, pub memory_bridge: MemoryBridge, /// Bus to send byte checks to @@ -40,26 +36,26 @@ pub struct Sha256VmAir { /// Maximum number of bits allowed for an address pointer /// Must be at least 24 pub ptr_max_bits: usize, - pub(super) sha256_subair: Sha256Air, + pub(super) sha_subair: Sha2Air, pub(super) padding_encoder: Encoder, } -impl BaseAirWithPublicValues for Sha256VmAir {} -impl PartitionedBaseAir for Sha256VmAir {} -impl BaseAir for Sha256VmAir { +impl BaseAirWithPublicValues for Sha2VmAir {} +impl PartitionedBaseAir for Sha2VmAir {} +impl BaseAir for Sha2VmAir { fn width(&self) -> usize { - SHA256VM_WIDTH + C::VM_WIDTH } } -impl Air for Sha256VmAir { +impl Air for Sha2VmAir { fn eval(&self, builder: &mut AB) { self.eval_padding(builder); self.eval_transitions(builder); self.eval_reads(builder); self.eval_last_row(builder); - self.sha256_subair.eval(builder, SHA256VM_CONTROL_WIDTH); + self.sha_subair.eval(builder, C::VM_CONTROL_WIDTH); } } @@ -86,6 +82,22 @@ pub(super) enum PaddingFlags { FirstPadding13, FirstPadding14, FirstPadding15, + FirstPadding16, + FirstPadding17, + FirstPadding18, + FirstPadding19, + FirstPadding20, + FirstPadding21, + FirstPadding22, + FirstPadding23, + FirstPadding24, + FirstPadding25, + FirstPadding26, + FirstPadding27, + FirstPadding28, + FirstPadding29, + FirstPadding30, + FirstPadding31, /// FIRST_PADDING_i_LastRow: it is the first row with padding and there are i cells of non-padding /// AND it is the last reading row of the message /// NOTE: if the Last row has padding it has to be at least 9 cells since the last 8 cells are padded with @@ -98,6 +110,15 @@ pub(super) enum PaddingFlags { FirstPadding5_LastRow, FirstPadding6_LastRow, FirstPadding7_LastRow, + FirstPadding8_LastRow, + FirstPadding9_LastRow, + FirstPadding10_LastRow, + FirstPadding11_LastRow, + FirstPadding12_LastRow, + FirstPadding13_LastRow, + FirstPadding14_LastRow, + FirstPadding15_LastRow, + /// The entire row is padding AND it is not the first row with padding /// AND it is the 4th row of the last block of the message EntirePaddingLastRow, @@ -111,84 +132,84 @@ impl PaddingFlags { } use PaddingFlags::*; -impl Sha256VmAir { +impl Sha2VmAir { /// Implement all necessary constraints for the padding fn eval_padding(&self, builder: &mut AB) { let main = builder.main(); let (local, next) = (main.row_slice(0), main.row_slice(1)); - let local_cols: &Sha256VmRoundCols = local[..SHA256VM_ROUND_WIDTH].borrow(); - let next_cols: &Sha256VmRoundCols = next[..SHA256VM_ROUND_WIDTH].borrow(); + let local_cols = ShaVmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); + let next_cols = ShaVmRoundColsRef::::from::(&next[..C::VM_ROUND_WIDTH]); // Constrain the sanity of the padding flags self.padding_encoder - .eval(builder, &local_cols.control.pad_flags); + .eval(builder, local_cols.control.pad_flags.as_slice().unwrap()); builder.assert_one(self.padding_encoder.contains_flag_range::( - &local_cols.control.pad_flags, + local_cols.control.pad_flags.as_slice().unwrap(), NotConsidered as usize..=EntirePadding as usize, )); - Self::eval_padding_transitions(self, builder, local_cols, next_cols); - Self::eval_padding_row(self, builder, local_cols); + Self::eval_padding_transitions(self, builder, &local_cols, &next_cols); + Self::eval_padding_row(self, builder, &local_cols); } fn eval_padding_transitions( &self, builder: &mut AB, - local: &Sha256VmRoundCols, - next: &Sha256VmRoundCols, + local: &ShaVmRoundColsRef, + next: &ShaVmRoundColsRef, ) { - let next_is_last_row = next.inner.flags.is_digest_row * next.inner.flags.is_last_block; + let next_is_last_row = *next.inner.flags.is_digest_row * *next.inner.flags.is_last_block; // Constrain that `padding_occured` is 1 on a suffix of rows in each message, excluding the last // digest row, and 0 everywhere else. Furthermore, the suffix starts in the first 4 rows of some block. - builder.assert_bool(local.control.padding_occurred); + builder.assert_bool(*local.control.padding_occurred); // Last round row in the last block has padding_occurred = 1 // This is the end of the suffix builder .when(next_is_last_row.clone()) - .assert_one(local.control.padding_occurred); + .assert_one(*local.control.padding_occurred); // Digest row in the last block has padding_occurred = 0 builder .when(next_is_last_row.clone()) - .assert_zero(next.control.padding_occurred); + .assert_zero(*next.control.padding_occurred); // If padding_occurred = 1 in the current row, then padding_occurred = 1 in the next row, // unless next is the last digest row builder - .when(local.control.padding_occurred - next_is_last_row.clone()) - .assert_one(next.control.padding_occurred); + .when(*local.control.padding_occurred - next_is_last_row.clone()) + .assert_one(*next.control.padding_occurred); // If next row is not first 4 rows of a block, then next.padding_occurred = local.padding_occurred. // So padding_occurred only changes in the first 4 rows of a block. builder .when_transition() - .when(not(next.inner.flags.is_first_4_rows) - next_is_last_row) + .when(not(*next.inner.flags.is_first_4_rows) - next_is_last_row) .assert_eq( - next.control.padding_occurred, - local.control.padding_occurred, + *next.control.padding_occurred, + *local.control.padding_occurred, ); // Constrain the that the start of the padding is correct let next_is_first_padding_row = - next.control.padding_occurred - local.control.padding_occurred; + *next.control.padding_occurred - *local.control.padding_occurred; // Row index if its between 0..4, else 0 - let next_row_idx = self.sha256_subair.row_idx_encoder.flag_with_val::( - &next.inner.flags.row_idx, - &(0..4).map(|x| (x, x)).collect::>(), + let next_row_idx = self.sha_subair.row_idx_encoder.flag_with_val::( + next.inner.flags.row_idx.as_slice().unwrap(), + &(0..C::MESSAGE_ROWS).map(|x| (x, x)).collect::>(), ); // How many non-padding cells there are in the next row. // Will be 0 on non-padding rows. let next_padding_offset = self.padding_encoder.flag_with_val::( - &next.control.pad_flags, - &(0..16) + next.control.pad_flags.as_slice().unwrap(), + &(0..C::MAX_FIRST_PADDING + 1) .map(|i| (FirstPadding0 as usize + i, i)) .collect::>(), ) + self.padding_encoder.flag_with_val::( - &next.control.pad_flags, - &(0..8) + next.control.pad_flags.as_slice().unwrap(), + &(0..C::MAX_FIRST_PADDING_LAST_ROW + 1) .map(|i| (FirstPadding0_LastRow as usize + i, i)) .collect::>(), ); @@ -197,10 +218,10 @@ impl Sha256VmAir { // - padding_occurred = 0 is constrained above // - next_row_idx = 0 since row_idx is not in 0..4 // - and next_padding_offset = 0 since `pad_flags = NotConsidered` - let expected_len = next.inner.flags.local_block_idx - * next.control.padding_occurred - * AB::Expr::from_canonical_usize(SHA256_BLOCK_U8S) - + next_row_idx * AB::Expr::from_canonical_usize(SHA256_READ_SIZE) + let expected_len = *next.inner.flags.local_block_idx + * *next.control.padding_occurred + * AB::Expr::from_canonical_usize(C::BLOCK_U8S) + + next_row_idx * AB::Expr::from_canonical_usize(C::READ_SIZE) + next_padding_offset; // Note: `next_is_first_padding_row` is either -1,0,1 @@ -208,158 +229,174 @@ impl Sha256VmAir { // If -1, then `next` must be the last digest row and so this constraint will be 0 == 0 builder.when(next_is_first_padding_row).assert_eq( expected_len, - next.control.len * next.control.padding_occurred, + *next.control.len * *next.control.padding_occurred, ); // Constrain the padding flags are of correct type (eg is not padding or first padding) let is_next_first_padding = self.padding_encoder.contains_flag_range::( - &next.control.pad_flags, - FirstPadding0 as usize..=FirstPadding7_LastRow as usize, + next.control.pad_flags.as_slice().unwrap(), + FirstPadding0 as usize..=(FirstPadding15_LastRow as usize), ); let is_next_last_padding = self.padding_encoder.contains_flag_range::( - &next.control.pad_flags, + next.control.pad_flags.as_slice().unwrap(), FirstPadding0_LastRow as usize..=EntirePaddingLastRow as usize, ); let is_next_entire_padding = self.padding_encoder.contains_flag_range::( - &next.control.pad_flags, + next.control.pad_flags.as_slice().unwrap(), EntirePaddingLastRow as usize..=EntirePadding as usize, ); - let is_next_not_considered = self - .padding_encoder - .contains_flag::(&next.control.pad_flags, &[NotConsidered as usize]); + let is_next_not_considered = self.padding_encoder.contains_flag::( + next.control.pad_flags.as_slice().unwrap(), + &[NotConsidered as usize], + ); - let is_next_not_padding = self - .padding_encoder - .contains_flag::(&next.control.pad_flags, &[NotPadding as usize]); + let is_next_not_padding = self.padding_encoder.contains_flag::( + next.control.pad_flags.as_slice().unwrap(), + &[NotPadding as usize], + ); let is_next_4th_row = self - .sha256_subair + .sha_subair .row_idx_encoder - .contains_flag::(&next.inner.flags.row_idx, &[3]); + .contains_flag::(next.inner.flags.row_idx.as_slice().unwrap(), &[3]); // `pad_flags` is `NotConsidered` on all rows except the first 4 rows of a block builder.assert_eq( - not(next.inner.flags.is_first_4_rows), + not(*next.inner.flags.is_first_4_rows), is_next_not_considered, ); // `pad_flags` is `EntirePadding` if the previous row is padding - builder.when(next.inner.flags.is_first_4_rows).assert_eq( - local.control.padding_occurred * next.control.padding_occurred, + builder.when(*next.inner.flags.is_first_4_rows).assert_eq( + *local.control.padding_occurred * *next.control.padding_occurred, is_next_entire_padding, ); // `pad_flags` is `FirstPadding*` if current row is padding and the previous row is not padding - builder.when(next.inner.flags.is_first_4_rows).assert_eq( - not(local.control.padding_occurred) * next.control.padding_occurred, + builder.when(*next.inner.flags.is_first_4_rows).assert_eq( + not(*local.control.padding_occurred) * *next.control.padding_occurred, is_next_first_padding, ); // `pad_flags` is `NotPadding` if current row is not padding builder - .when(next.inner.flags.is_first_4_rows) - .assert_eq(not(next.control.padding_occurred), is_next_not_padding); + .when(*next.inner.flags.is_first_4_rows) + .assert_eq(not(*next.control.padding_occurred), is_next_not_padding); // `pad_flags` is `*LastRow` on the row that contsrains the last four words of the message builder - .when(next.inner.flags.is_last_block) + .when(*next.inner.flags.is_last_block) .assert_eq(is_next_4th_row, is_next_last_padding); } fn eval_padding_row( &self, builder: &mut AB, - local: &Sha256VmRoundCols, + local: &ShaVmRoundColsRef, ) { - let message: [AB::Var; SHA256_READ_SIZE] = array::from_fn(|i| { - local.inner.message_schedule.carry_or_buffer[i / (SHA256_WORD_U8S)] - [i % (SHA256_WORD_U8S)] - }); + let message = (0..C::READ_SIZE) + .map(|i| { + local.inner.message_schedule.carry_or_buffer[[i / (C::WORD_U8S), i % (C::WORD_U8S)]] + }) + .collect::>(); let get_ith_byte = |i: usize| { - let word_idx = i / SHA256_ROUNDS_PER_ROW; - let word = local.inner.message_schedule.w[word_idx].map(|x| x.into()); + let word_idx = i / C::WORD_U8S; + let word = local + .inner + .message_schedule + .w + .row(word_idx) + .mapv(|x| x.into()); // Need to reverse the byte order to match the endianness of the memory - let byte_idx = 4 - i % 4 - 1; - compose::(&word[byte_idx * 8..(byte_idx + 1) * 8], 1) + let byte_idx = C::WORD_U8S - i % C::WORD_U8S - 1; + compose::( + &word.as_slice().unwrap()[byte_idx * 8..(byte_idx + 1) * 8], + 1, + ) }; - let is_not_padding = self - .padding_encoder - .contains_flag::(&local.control.pad_flags, &[NotPadding as usize]); + let is_not_padding = self.padding_encoder.contains_flag::( + local.control.pad_flags.as_slice().unwrap(), + &[NotPadding as usize], + ); // Check the `w`s on case by case basis for (i, message_byte) in message.iter().enumerate() { let w = get_ith_byte(i); let should_be_message = is_not_padding.clone() - + if i < 15 { + + if i < C::MAX_FIRST_PADDING { self.padding_encoder.contains_flag_range::( - &local.control.pad_flags, - FirstPadding0 as usize + i + 1..=FirstPadding15 as usize, + local.control.pad_flags.as_slice().unwrap(), + FirstPadding0 as usize + i + 1 + ..=FirstPadding0 as usize + C::MAX_FIRST_PADDING, ) } else { AB::Expr::ZERO } - + if i < 7 { + + if i < C::MAX_FIRST_PADDING_LAST_ROW { self.padding_encoder.contains_flag_range::( - &local.control.pad_flags, - FirstPadding0_LastRow as usize + i + 1..=FirstPadding7_LastRow as usize, + local.control.pad_flags.as_slice().unwrap(), + FirstPadding0_LastRow as usize + i + 1 + ..=FirstPadding0_LastRow as usize + C::MAX_FIRST_PADDING_LAST_ROW, ) } else { AB::Expr::ZERO }; + builder .when(should_be_message) .assert_eq(w.clone(), *message_byte); - let should_be_zero = self - .padding_encoder - .contains_flag::(&local.control.pad_flags, &[EntirePadding as usize]) - + if i < 12 { - self.padding_encoder.contains_flag::( - &local.control.pad_flags, - &[EntirePaddingLastRow as usize], - ) + if i > 0 { - self.padding_encoder.contains_flag_range::( - &local.control.pad_flags, - FirstPadding0_LastRow as usize - ..=min( - FirstPadding0_LastRow as usize + i - 1, - FirstPadding7_LastRow as usize, - ), - ) - } else { - AB::Expr::ZERO - } - } else { - AB::Expr::ZERO - } - + if i > 0 { + let should_be_zero = self.padding_encoder.contains_flag::( + local.control.pad_flags.as_slice().unwrap(), + &[EntirePadding as usize], + ) + + // - 4 because the last 4 bytes are the padded length + if i < C::CELLS_PER_ROW - 4 { + self.padding_encoder.contains_flag::( + local.control.pad_flags.as_slice().unwrap(), + &[EntirePaddingLastRow as usize], + ) + if i > 0 { self.padding_encoder.contains_flag_range::( - &local.control.pad_flags, - FirstPadding0 as usize..=FirstPadding0 as usize + i - 1, + local.control.pad_flags.as_slice().unwrap(), + FirstPadding0_LastRow as usize + ..=min( + FirstPadding0_LastRow as usize + i - 1, + FirstPadding0_LastRow as usize + C::MAX_FIRST_PADDING_LAST_ROW, + ), ) } else { AB::Expr::ZERO - }; + } + } else { + AB::Expr::ZERO + } + if i > 0 { + self.padding_encoder.contains_flag_range::( + local.control.pad_flags.as_slice().unwrap(), + FirstPadding0 as usize..=FirstPadding0 as usize + i - 1, + ) + } else { + AB::Expr::ZERO + }; builder.when(should_be_zero).assert_zero(w.clone()); // Assumes bit-length of message is a multiple of 8 (message is bytes) // This is true because the message is given as &[u8] - let should_be_128 = self - .padding_encoder - .contains_flag::(&local.control.pad_flags, &[FirstPadding0 as usize + i]) - + if i < 8 { - self.padding_encoder.contains_flag::( - &local.control.pad_flags, - &[FirstPadding0_LastRow as usize + i], - ) - } else { - AB::Expr::ZERO - }; + let should_be_128 = self.padding_encoder.contains_flag::( + local.control.pad_flags.as_slice().unwrap(), + &[FirstPadding0 as usize + i], + ) + if i < 8 { + self.padding_encoder.contains_flag::( + local.control.pad_flags.as_slice().unwrap(), + &[FirstPadding0_LastRow as usize + i], + ) + } else { + AB::Expr::ZERO + }; builder .when(should_be_128) @@ -369,18 +406,18 @@ impl Sha256VmAir { } let appended_len = compose::( &[ - get_ith_byte(15), - get_ith_byte(14), - get_ith_byte(13), - get_ith_byte(12), + get_ith_byte(C::CELLS_PER_ROW - 1), + get_ith_byte(C::CELLS_PER_ROW - 2), + get_ith_byte(C::CELLS_PER_ROW - 3), + get_ith_byte(C::CELLS_PER_ROW - 4), ], RV32_CELL_BITS, ); - let actual_len = local.control.len; + let actual_len = *local.control.len; let is_last_padding_row = self.padding_encoder.contains_flag_range::( - &local.control.pad_flags, + local.control.pad_flags.as_slice().unwrap(), FirstPadding0_LastRow as usize..=EntirePaddingLastRow as usize, ); @@ -391,12 +428,12 @@ impl Sha256VmAir { // We constrain that the appended length is in bytes builder.when(is_last_padding_row.clone()).assert_zero( - local.inner.message_schedule.w[3][0] - + local.inner.message_schedule.w[3][1] - + local.inner.message_schedule.w[3][2], + local.inner.message_schedule.w[[3, 0]] + + local.inner.message_schedule.w[[3, 1]] + + local.inner.message_schedule.w[[3, 2]], ); - // We can't support messages longer than 2^30 bytes because the length has to fit in a field element. + // We can't support messages longer than 2^29 bytes because the length has to fit in a field element. // So, constrain that the first 4 bytes of the length are 0. // Thus, the bit-length is < 2^32 so the message is < 2^29 bytes. for i in 8..12 { @@ -409,37 +446,36 @@ impl Sha256VmAir { fn eval_transitions(&self, builder: &mut AB) { let main = builder.main(); let (local, next) = (main.row_slice(0), main.row_slice(1)); - let local_cols: &Sha256VmRoundCols = local[..SHA256VM_ROUND_WIDTH].borrow(); - let next_cols: &Sha256VmRoundCols = next[..SHA256VM_ROUND_WIDTH].borrow(); + let local_cols = ShaVmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); + let next_cols = ShaVmRoundColsRef::::from::(&next[..C::VM_ROUND_WIDTH]); let is_last_row = - local_cols.inner.flags.is_last_block * local_cols.inner.flags.is_digest_row; - + *local_cols.inner.flags.is_last_block * *local_cols.inner.flags.is_digest_row; // Len should be the same for the entire message builder .when_transition() .when(not::(is_last_row.clone())) - .assert_eq(next_cols.control.len, local_cols.control.len); + .assert_eq(*next_cols.control.len, *local_cols.control.len); // Read ptr should increment by [SHA256_READ_SIZE] for the first 4 rows and stay the same otherwise - let read_ptr_delta = local_cols.inner.flags.is_first_4_rows - * AB::Expr::from_canonical_usize(SHA256_READ_SIZE); + let read_ptr_delta = + *local_cols.inner.flags.is_first_4_rows * AB::Expr::from_canonical_usize(C::READ_SIZE); builder .when_transition() .when(not::(is_last_row.clone())) .assert_eq( - next_cols.control.read_ptr, - local_cols.control.read_ptr + read_ptr_delta, + *next_cols.control.read_ptr, + *local_cols.control.read_ptr + read_ptr_delta, ); // Timestamp should increment by 1 for the first 4 rows and stay the same otherwise - let timestamp_delta = local_cols.inner.flags.is_first_4_rows * AB::Expr::ONE; + let timestamp_delta = *local_cols.inner.flags.is_first_4_rows * AB::Expr::ONE; builder .when_transition() .when(not::(is_last_row.clone())) .assert_eq( - next_cols.control.cur_timestamp, - local_cols.control.cur_timestamp + timestamp_delta, + *next_cols.control.cur_timestamp, + *local_cols.control.cur_timestamp + timestamp_delta, ); } @@ -447,30 +483,57 @@ impl Sha256VmAir { fn eval_reads(&self, builder: &mut AB) { let main = builder.main(); let local = main.row_slice(0); - let local_cols: &Sha256VmRoundCols = local[..SHA256VM_ROUND_WIDTH].borrow(); - - let message: [AB::Var; SHA256_READ_SIZE] = array::from_fn(|i| { - local_cols.inner.message_schedule.carry_or_buffer[i / (SHA256_WORD_U16S * 2)] - [i % (SHA256_WORD_U16S * 2)] - }); - - self.memory_bridge - .read( - MemoryAddress::new( - AB::Expr::from_canonical_u32(RV32_MEMORY_AS), - local_cols.control.read_ptr, - ), - message, - local_cols.control.cur_timestamp, - &local_cols.read_aux, - ) - .eval(builder, local_cols.inner.flags.is_first_4_rows); + let local_cols = ShaVmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); + + let message: Vec = (0..C::READ_SIZE) + .map(|i| { + local_cols.inner.message_schedule.carry_or_buffer + [[i / (C::WORD_U16S * 2), i % (C::WORD_U16S * 2)]] + }) + .collect(); + + match C::VARIANT { + Sha2Variant::Sha256 => { + let message: [AB::Var; Sha256Config::READ_SIZE] = + message.try_into().unwrap_or_else(|_| { + panic!("message is not the correct size"); + }); + self.memory_bridge + .read( + MemoryAddress::new( + AB::Expr::from_canonical_u32(RV32_MEMORY_AS), + *local_cols.control.read_ptr, + ), + message, + *local_cols.control.cur_timestamp, + local_cols.read_aux, + ) + .eval(builder, *local_cols.inner.flags.is_first_4_rows); + } + Sha2Variant::Sha512 => { + let message: [AB::Var; Sha512Config::READ_SIZE] = + message.try_into().unwrap_or_else(|_| { + panic!("message is not the correct size"); + }); + self.memory_bridge + .read( + MemoryAddress::new( + AB::Expr::from_canonical_u32(RV32_MEMORY_AS), + *local_cols.control.read_ptr, + ), + message, + *local_cols.control.cur_timestamp, + local_cols.read_aux, + ) + .eval(builder, *local_cols.inner.flags.is_first_4_rows); + } + } } /// Implement the constraints for the last row of a message fn eval_last_row(&self, builder: &mut AB) { let main = builder.main(); let local = main.row_slice(0); - let local_cols: &Sha256VmDigestCols = local[..SHA256VM_DIGEST_WIDTH].borrow(); + let local_cols = ShaVmDigestColsRef::::from::(&local[..C::VM_DIGEST_WIDTH]); let timestamp: AB::Var = local_cols.from_state.timestamp; let mut timestamp_delta: usize = 0; @@ -480,44 +543,55 @@ impl Sha256VmAir { }; let is_last_row = - local_cols.inner.flags.is_last_block * local_cols.inner.flags.is_digest_row; + *local_cols.inner.flags.is_last_block * *local_cols.inner.flags.is_digest_row; + let dst_ptr: [AB::Var; RV32_REGISTER_NUM_LIMBS] = + local_cols.dst_ptr.to_vec().try_into().unwrap_or_else(|_| { + panic!("dst_ptr is not the correct size"); + }); self.memory_bridge .read( MemoryAddress::new( AB::Expr::from_canonical_u32(RV32_REGISTER_AS), - local_cols.rd_ptr, + *local_cols.rd_ptr, ), - local_cols.dst_ptr, + dst_ptr, timestamp_pp(), &local_cols.register_reads_aux[0], ) .eval(builder, is_last_row.clone()); + let src_ptr: [AB::Var; RV32_REGISTER_NUM_LIMBS] = + local_cols.src_ptr.to_vec().try_into().unwrap_or_else(|_| { + panic!("src_ptr is not the correct size"); + }); self.memory_bridge .read( MemoryAddress::new( AB::Expr::from_canonical_u32(RV32_REGISTER_AS), - local_cols.rs1_ptr, + *local_cols.rs1_ptr, ), - local_cols.src_ptr, + src_ptr, timestamp_pp(), &local_cols.register_reads_aux[1], ) .eval(builder, is_last_row.clone()); + let len_data: [AB::Var; RV32_REGISTER_NUM_LIMBS] = + local_cols.len_data.to_vec().try_into().unwrap_or_else(|_| { + panic!("len_data is not the correct size"); + }); self.memory_bridge .read( MemoryAddress::new( AB::Expr::from_canonical_u32(RV32_REGISTER_AS), - local_cols.rs2_ptr, + *local_cols.rs2_ptr, ), - local_cols.len_data, + len_data, timestamp_pp(), &local_cols.register_reads_aux[2], ) .eval(builder, is_last_row.clone()); - // range check that the memory pointers don't overflow // Note: no need to range check the length since we read from memory step by step and // the memory bus will catch any memory accesses beyond ptr_max_bits @@ -534,59 +608,125 @@ impl Sha256VmAir { .eval(builder, is_last_row.clone()); // the number of reads that happened to read the entire message: we do 4 reads per block - let time_delta = (local_cols.inner.flags.local_block_idx + AB::Expr::ONE) + let time_delta = (*local_cols.inner.flags.local_block_idx + AB::Expr::ONE) * AB::Expr::from_canonical_usize(4); // Every time we read the message we increment the read pointer by SHA256_READ_SIZE - let read_ptr_delta = time_delta.clone() * AB::Expr::from_canonical_usize(SHA256_READ_SIZE); - - let result: [AB::Var; SHA256_WORD_U8S * SHA256_HASH_WORDS] = array::from_fn(|i| { - // The limbs are written in big endian order to the memory so need to be reversed - local_cols.inner.final_hash[i / SHA256_WORD_U8S] - [SHA256_WORD_U8S - i % SHA256_WORD_U8S - 1] - }); + let read_ptr_delta = time_delta.clone() * AB::Expr::from_canonical_usize(C::READ_SIZE); - let dst_ptr_val = - compose::(&local_cols.dst_ptr.map(|x| x.into()), RV32_CELL_BITS); + let result: Vec = (0..C::DIGEST_SIZE) + .map(|i| { + // The limbs are written in big endian order to the memory so need to be reversed + local_cols.inner.final_hash[[i / C::WORD_U8S, C::WORD_U8S - i % C::WORD_U8S - 1]] + }) + .collect(); - // Note: revisit in the future to do 2 block writes of 16 cells instead of 1 block write of 32 cells - // This could be beneficial as the output is often an input for another hash - self.memory_bridge - .write( - MemoryAddress::new(AB::Expr::from_canonical_u32(RV32_MEMORY_AS), dst_ptr_val), - result, - timestamp_pp() + time_delta.clone(), - &local_cols.writes_aux, - ) - .eval(builder, is_last_row.clone()); + let dst_ptr_val = compose::( + local_cols.dst_ptr.mapv(|x| x.into()).as_slice().unwrap(), + RV32_CELL_BITS, + ); + match C::VARIANT { + Sha2Variant::Sha256 => { + debug_assert_eq!(C::NUM_WRITES, 1); + debug_assert_eq!(local_cols.writes_aux_base.len(), 1); + debug_assert_eq!(local_cols.writes_aux_prev_data.nrows(), 1); + let prev_data: [AB::Var; Sha256Config::DIGEST_SIZE] = local_cols + .writes_aux_prev_data + .row(0) + .to_vec() + .try_into() + .unwrap_or_else(|_| { + panic!("writes_aux_prev_data is not the correct size"); + }); + // Note: revisit in the future to do 2 block writes of 16 cells instead of 1 block write of 32 cells + // This could be beneficial as the output is often an input for another hash + self.memory_bridge + .write( + MemoryAddress::new( + AB::Expr::from_canonical_u32(RV32_MEMORY_AS), + dst_ptr_val, + ), + result.try_into().unwrap_or_else(|_| { + panic!("result is not the correct size"); + }), + timestamp_pp() + time_delta.clone(), + &MemoryWriteAuxCols::from_base(local_cols.writes_aux_base[0], prev_data), + ) + .eval(builder, is_last_row.clone()); + } + Sha2Variant::Sha512 => { + debug_assert_eq!(C::NUM_WRITES, 2); + debug_assert_eq!(local_cols.writes_aux_base.len(), 2); + debug_assert_eq!(local_cols.writes_aux_prev_data.nrows(), 2); + // write the digest in two halves because we only support writes up to 32 bytes + for i in 0..Sha512Config::NUM_WRITES { + // for i in 0..1 { + let prev_data: [AB::Var; Sha512Config::WRITE_SIZE] = local_cols + .writes_aux_prev_data + .row(i) + .to_vec() + .try_into() + .unwrap_or_else(|_| { + panic!("writes_aux_prev_data is not the correct size"); + }); + + self.memory_bridge + .write( + MemoryAddress::new( + AB::Expr::from_canonical_u32(RV32_MEMORY_AS), + dst_ptr_val.clone() + + AB::Expr::from_canonical_usize(i * Sha512Config::WRITE_SIZE), + ), + result + [i * Sha512Config::WRITE_SIZE..(i + 1) * Sha512Config::WRITE_SIZE] + .try_into() + .unwrap_or_else(|_| { + panic!("result is not the correct size"); + }), + timestamp_pp() + time_delta.clone(), + &MemoryWriteAuxCols::from_base( + local_cols.writes_aux_base[i], + prev_data, + ), + ) + .eval(builder, is_last_row.clone()); + } + } + } self.execution_bridge .execute_and_increment_pc( - AB::Expr::from_canonical_usize(Rv32Sha256Opcode::SHA256.global_opcode().as_usize()), + AB::Expr::from_canonical_usize(C::OPCODE.global_opcode().as_usize()), [ - local_cols.rd_ptr.into(), - local_cols.rs1_ptr.into(), - local_cols.rs2_ptr.into(), + >::into(*local_cols.rd_ptr), + >::into(*local_cols.rs1_ptr), + >::into(*local_cols.rs2_ptr), AB::Expr::from_canonical_u32(RV32_REGISTER_AS), AB::Expr::from_canonical_u32(RV32_MEMORY_AS), ], - local_cols.from_state, + *local_cols.from_state, AB::Expr::from_canonical_usize(timestamp_delta) + time_delta.clone(), ) .eval(builder, is_last_row.clone()); // Assert that we read the correct length of the message - let len_val = compose::(&local_cols.len_data.map(|x| x.into()), RV32_CELL_BITS); + let len_val = compose::( + local_cols.len_data.mapv(|x| x.into()).as_slice().unwrap(), + RV32_CELL_BITS, + ); builder .when(is_last_row.clone()) - .assert_eq(local_cols.control.len, len_val); + .assert_eq(*local_cols.control.len, len_val); // Assert that we started reading from the correct pointer initially - let src_val = compose::(&local_cols.src_ptr.map(|x| x.into()), RV32_CELL_BITS); + let src_val = compose::( + local_cols.src_ptr.mapv(|x| x.into()).as_slice().unwrap(), + RV32_CELL_BITS, + ); builder .when(is_last_row.clone()) - .assert_eq(local_cols.control.read_ptr, src_val + read_ptr_delta); + .assert_eq(*local_cols.control.read_ptr, src_val + read_ptr_delta); // Assert that we started reading from the correct timestamp builder.when(is_last_row.clone()).assert_eq( - local_cols.control.cur_timestamp, + *local_cols.control.cur_timestamp, local_cols.from_state.timestamp + AB::Expr::from_canonical_u32(3) + time_delta, ); } diff --git a/extensions/sha256/circuit/src/sha256_chip/columns.rs b/extensions/sha256/circuit/src/sha256_chip/columns.rs index 5c98f4de97..447da18b94 100644 --- a/extensions/sha256/circuit/src/sha256_chip/columns.rs +++ b/extensions/sha256/circuit/src/sha256_chip/columns.rs @@ -2,29 +2,73 @@ use openvm_circuit::{ arch::ExecutionState, - system::memory::offline_checker::{MemoryReadAuxCols, MemoryWriteAuxCols}, + system::memory::offline_checker::{MemoryBaseAuxCols, MemoryReadAuxCols}, }; -use openvm_circuit_primitives::AlignedBorrow; use openvm_instructions::riscv::RV32_REGISTER_NUM_LIMBS; -use openvm_sha_air::{Sha256DigestCols, Sha256RoundCols}; +use openvm_sha_air::{ + ShaDigestCols, ShaDigestColsRef, ShaDigestColsRefMut, ShaRoundCols, ShaRoundColsRef, + ShaRoundColsRefMut, +}; +use openvm_sha_macros::ColsRef; -use super::{SHA256_REGISTER_READS, SHA256_WRITE_SIZE}; +use super::SHA_REGISTER_READS; +use crate::ShaChipConfig; -/// the first 16 rows of every SHA256 block will be of type Sha256VmRoundCols and the last row will be of type Sha256VmDigestCols +/// the first C::ROUND_ROWS rows of every SHA block will be of type ShaVmRoundCols and the last row will be of type ShaVmDigestCols #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256VmRoundCols { - pub control: Sha256VmControlCols, - pub inner: Sha256RoundCols, +#[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaChipConfig)] +pub struct ShaVmRoundCols< + 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 control: ShaVmControlCols, + pub inner: ShaRoundCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + >, + #[aligned_borrow] pub read_aux: MemoryReadAuxCols, } #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256VmDigestCols { - pub control: Sha256VmControlCols, - pub inner: Sha256DigestCols, - +#[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaChipConfig)] +pub struct ShaVmDigestCols< + 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, + const DIGEST_SIZE: usize, + const NUM_WRITES: usize, + const WRITE_SIZE: usize, +> { + pub control: ShaVmControlCols, + pub inner: ShaDigestCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + >, + #[aligned_borrow] pub from_state: ExecutionState, /// It is counter intuitive, but we will constrain the register reads on the very last row of every message pub rd_ptr: T, @@ -33,14 +77,21 @@ pub struct Sha256VmDigestCols { pub dst_ptr: [T; RV32_REGISTER_NUM_LIMBS], pub src_ptr: [T; RV32_REGISTER_NUM_LIMBS], pub len_data: [T; RV32_REGISTER_NUM_LIMBS], - pub register_reads_aux: [MemoryReadAuxCols; SHA256_REGISTER_READS], - pub writes_aux: MemoryWriteAuxCols, + #[aligned_borrow] + pub register_reads_aux: [MemoryReadAuxCols; SHA_REGISTER_READS], + // We store the fields of MemoryWriteAuxCols here because the length of prev_data depends on the sha variant + #[aligned_borrow] + pub writes_aux_base: [MemoryBaseAuxCols; NUM_WRITES], + pub writes_aux_prev_data: [[T; WRITE_SIZE]; NUM_WRITES], } +pub type Sha256VmDigestCols = ShaVmDigestCols; + /// These are the columns that are used on both round and digest rows #[repr(C)] -#[derive(Clone, Copy, Debug, AlignedBorrow)] -pub struct Sha256VmControlCols { +#[derive(Clone, Copy, Debug, ColsRef)] +#[config(ShaChipConfig)] +pub struct ShaVmControlCols { /// Note: We will use the buffer in `inner.message_schedule` as the message data /// This is the length of the entire message in bytes pub len: T, @@ -48,20 +99,7 @@ pub struct Sha256VmControlCols { pub cur_timestamp: T, pub read_ptr: T, /// Padding flags which will be used to encode the the number of non-padding cells in the current row - pub pad_flags: [T; 6], + pub pad_flags: [T; 9], /// A boolean flag that indicates whether a padding already occurred pub padding_occurred: T, } - -/// Width of the Sha256VmControlCols -pub const SHA256VM_CONTROL_WIDTH: usize = Sha256VmControlCols::::width(); -/// Width of the Sha256VmRoundCols -pub const SHA256VM_ROUND_WIDTH: usize = Sha256VmRoundCols::::width(); -/// Width of the Sha256VmDigestCols -pub const SHA256VM_DIGEST_WIDTH: usize = Sha256VmDigestCols::::width(); -/// Width of the Sha256Cols -pub const SHA256VM_WIDTH: usize = if SHA256VM_ROUND_WIDTH > SHA256VM_DIGEST_WIDTH { - SHA256VM_ROUND_WIDTH -} else { - SHA256VM_DIGEST_WIDTH -}; diff --git a/extensions/sha256/circuit/src/sha256_chip/config.rs b/extensions/sha256/circuit/src/sha256_chip/config.rs new file mode 100644 index 0000000000..7989e916b5 --- /dev/null +++ b/extensions/sha256/circuit/src/sha256_chip/config.rs @@ -0,0 +1,75 @@ +use openvm_instructions::riscv::RV32_CELL_BITS; +use openvm_sha256_transpiler::Rv32Sha2Opcode; +use openvm_sha_air::{Sha256Config, Sha512Config, ShaConfig}; + +use super::{ShaVmControlColsRef, ShaVmDigestColsRef, ShaVmRoundColsRef}; + +pub enum Sha2Variant { + Sha256, + Sha512, +} + +pub trait ShaChipConfig: ShaConfig { + // Differentiate between the two SHA256 variants + const VARIANT: Sha2Variant; + // Name of the opcode + const OPCODE_NAME: &'static str; + /// Width of the ShaVmControlCols + const VM_CONTROL_WIDTH: usize = ShaVmControlColsRef::::width::(); + /// Width of the ShaVmRoundCols + const VM_ROUND_WIDTH: usize = ShaVmRoundColsRef::::width::(); + /// Width of the ShaVmDigestCols + const VM_DIGEST_WIDTH: usize = ShaVmDigestColsRef::::width::(); + /// Width of the ShaVmCols + const VM_WIDTH: usize = if Self::VM_ROUND_WIDTH > Self::VM_DIGEST_WIDTH { + Self::VM_ROUND_WIDTH + } else { + Self::VM_DIGEST_WIDTH + }; + /// Number of bits to use when padding the message length + const MESSAGE_LENGTH_BITS: usize; + /// Maximum i such that `FirstPadding_i` is a valid padding flag + const MAX_FIRST_PADDING: usize = Self::CELLS_PER_ROW - 1; + /// Maximum i such that `FirstPadding_i_LastRow` is a valid padding flag + const MAX_FIRST_PADDING_LAST_ROW: usize = + Self::CELLS_PER_ROW - Self::MESSAGE_LENGTH_BITS / 8 - 1; + /// OpenVM Opcode for the instruction + const OPCODE: Rv32Sha2Opcode; + + // ==== Constants for register/memory adapter ==== + // Number of rv32 cells read in a SHA256 block + const BLOCK_CELLS: usize = Self::BLOCK_BITS / RV32_CELL_BITS; + /// Number of rows we will do a read on for each SHA256 block + const NUM_READ_ROWS: usize = Self::MESSAGE_ROWS; + + /// Number of cells to read in a single memory access + const READ_SIZE: usize = Self::WORD_U8S * Self::ROUNDS_PER_ROW; + /// Number of cells in the digest + const DIGEST_SIZE: usize = Self::WORD_U8S * Self::HASH_WORDS; + /// Digest will be written in NUM_WRITES parts of equal size + /// NUM_WRITES must divide DIGEST_SIZE + const NUM_WRITES: usize; + /// Size of each write + const WRITE_SIZE: usize = Self::DIGEST_SIZE / Self::NUM_WRITES; +} + +/// Register reads to get dst, src, len +pub const SHA_REGISTER_READS: usize = 3; + +impl ShaChipConfig for Sha256Config { + const VARIANT: Sha2Variant = Sha2Variant::Sha256; + const OPCODE_NAME: &'static str = "SHA256"; + const MESSAGE_LENGTH_BITS: usize = 64; + const NUM_WRITES: usize = 1; + const OPCODE: Rv32Sha2Opcode = Rv32Sha2Opcode::SHA256; +} + +// Currently same as Sha256Config, but can configure later +impl ShaChipConfig for Sha512Config { + const VARIANT: Sha2Variant = Sha2Variant::Sha512; + const OPCODE_NAME: &'static str = "SHA512"; + const MESSAGE_LENGTH_BITS: usize = 128; + // Use 2 writes because we only support writes up to 32 bytes + const NUM_WRITES: usize = 2; + const OPCODE: Rv32Sha2Opcode = Rv32Sha2Opcode::SHA512; +} diff --git a/extensions/sha256/circuit/src/sha256_chip/mod.rs b/extensions/sha256/circuit/src/sha256_chip/mod.rs index 6c8730b605..37a82e7725 100644 --- a/extensions/sha256/circuit/src/sha256_chip/mod.rs +++ b/extensions/sha256/circuit/src/sha256_chip/mod.rs @@ -1,7 +1,6 @@ //! Sha256 hasher. Handles full sha256 hashing with padding. //! variable length inputs read from VM memory. use std::{ - array, cmp::{max, min}, sync::{Arc, Mutex}, }; @@ -15,42 +14,33 @@ use openvm_circuit_primitives::{ use openvm_instructions::{ instruction::Instruction, program::DEFAULT_PC_STEP, - riscv::{RV32_CELL_BITS, RV32_MEMORY_AS, RV32_REGISTER_AS}, + riscv::{RV32_MEMORY_AS, RV32_REGISTER_AS}, LocalOpcode, }; use openvm_rv32im_circuit::adapters::read_rv32_register; -use openvm_sha256_transpiler::Rv32Sha256Opcode; -use openvm_sha_air::{Sha256Air, SHA256_BLOCK_BITS}; +use openvm_sha256_transpiler::Rv32Sha2Opcode; +use openvm_sha_air::{Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{interaction::BusIndex, p3_field::PrimeField32}; use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256}; +use sha2::{Digest, Sha256, Sha512}; mod air; mod columns; +mod config; mod trace; pub use air::*; pub use columns::*; +pub use config::*; use openvm_circuit::system::memory::{MemoryController, OfflineMemory, RecordId}; #[cfg(test)] mod tests; -// ==== Constants for register/memory adapter ==== -/// Register reads to get dst, src, len -const SHA256_REGISTER_READS: usize = 3; -/// Number of cells to read in a single memory access -const SHA256_READ_SIZE: usize = 16; -/// Number of cells to write in a single memory access -const SHA256_WRITE_SIZE: usize = 32; -/// Number of rv32 cells read in a SHA256 block -pub const SHA256_BLOCK_CELLS: usize = SHA256_BLOCK_BITS / RV32_CELL_BITS; -/// Number of rows we will do a read on for each SHA256 block -pub const SHA256_NUM_READ_ROWS: usize = SHA256_BLOCK_CELLS / SHA256_READ_SIZE; -pub struct Sha256VmChip { - pub air: Sha256VmAir, +pub struct Sha2VmChip { + pub air: Sha2VmAir, /// IO and memory data necessary for each opcode call - pub records: Vec>, + pub records: Vec>, pub offline_memory: Arc>>, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, @@ -58,17 +48,17 @@ pub struct Sha256VmChip { } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] -pub struct Sha256Record { +pub struct Sha2Record { pub from_state: ExecutionState, pub dst_read: RecordId, pub src_read: RecordId, pub len_read: RecordId, - pub input_records: Vec<[RecordId; SHA256_NUM_READ_ROWS]>, - pub input_message: Vec<[[u8; SHA256_READ_SIZE]; SHA256_NUM_READ_ROWS]>, - pub digest_write: RecordId, + pub input_records: Vec>, // type is like Vec<[RecordId; C::NUM_READ_ROWS]> + pub input_message: Vec>>, // type is like Vec<[[u8; C::SHA256_READ_SIZE]; C::SHA256_NUM_READ_ROWS]> + pub digest_writes: Vec, // one write for sha256, two for sha512 } -impl Sha256VmChip { +impl Sha2VmChip { pub fn new( SystemPort { execution_bus, @@ -82,12 +72,12 @@ impl Sha256VmChip { offline_memory: Arc>>, ) -> Self { Self { - air: Sha256VmAir::new( + air: Sha2VmAir::new( ExecutionBridge::new(execution_bus, program_bus), memory_bridge, bitwise_lookup_chip.bus(), address_bits, - Sha256Air::new(bitwise_lookup_chip.bus(), self_bus_idx), + Sha2Air::::new(bitwise_lookup_chip.bus(), self_bus_idx), Encoder::new(PaddingFlags::COUNT, 2, false), ), bitwise_lookup_chip, @@ -98,7 +88,7 @@ impl Sha256VmChip { } } -impl InstructionExecutor for Sha256VmChip { +impl InstructionExecutor for Sha2VmChip { fn execute( &mut self, memory: &mut MemoryController, @@ -115,7 +105,10 @@ impl InstructionExecutor for Sha256VmChip { .. } = instruction; let local_opcode = opcode.local_opcode_idx(self.offset); - debug_assert_eq!(local_opcode, Rv32Sha256Opcode::SHA256.local_usize()); + debug_assert!( + local_opcode == Rv32Sha2Opcode::SHA256.local_usize() + || local_opcode == Rv32Sha2Opcode::SHA512.local_usize() + ); debug_assert_eq!(d, F::from_canonical_u32(RV32_REGISTER_AS)); debug_assert_eq!(e, F::from_canonical_u32(RV32_MEMORY_AS)); @@ -132,57 +125,33 @@ impl InstructionExecutor for Sha256VmChip { assert!(len < (1 << self.air.ptr_max_bits)); } - // need to pad with one 1 bit, 64 bits for the message length and then pad until the length is divisible by [SHA256_BLOCK_BITS] - let num_blocks = ((len << 3) as usize + 1 + 64).div_ceil(SHA256_BLOCK_BITS); + // need to pad with one 1 bit, [C::MESSAGE_LENGTH_BITS] bits for the message length and then pad until the length is divisible by [C::BLOCK_BITS] + let num_blocks = ((len << 3) as usize + 1 + C::MESSAGE_LENGTH_BITS).div_ceil(C::BLOCK_BITS); - // we will read [num_blocks] * [SHA256_BLOCK_CELLS] cells but only [len] cells will be used - debug_assert!( - src as usize + num_blocks * SHA256_BLOCK_CELLS <= (1 << self.air.ptr_max_bits) - ); - let mut hasher = Sha256::new(); - let mut input_records = Vec::with_capacity(num_blocks * SHA256_NUM_READ_ROWS); - let mut input_message = Vec::with_capacity(num_blocks * SHA256_NUM_READ_ROWS); - let mut read_ptr = src; - for _ in 0..num_blocks { - let block_reads_records = array::from_fn(|i| { - memory.read( - e, - F::from_canonical_u32(read_ptr + (i * SHA256_READ_SIZE) as u32), - ) - }); - let block_reads_bytes = array::from_fn(|i| { - // we add to the hasher only the bytes that are part of the message - let num_reads = min( - SHA256_READ_SIZE, - (max(read_ptr, src + len) - read_ptr) as usize, - ); - let row_input = block_reads_records[i] - .1 - .map(|x| x.as_canonical_u32().try_into().unwrap()); - hasher.update(&row_input[..num_reads]); - read_ptr += SHA256_READ_SIZE as u32; - row_input - }); - input_records.push(block_reads_records.map(|x| x.0)); - input_message.push(block_reads_bytes); - } + // we will read [num_blocks] * [C::BLOCK_CELLS] cells but only [len] cells will be used + debug_assert!(src as usize + num_blocks * C::BLOCK_CELLS <= (1 << self.air.ptr_max_bits)); - let mut digest = [0u8; SHA256_WRITE_SIZE]; - digest.copy_from_slice(hasher.finalize().as_ref()); - let (digest_write, _) = memory.write( - e, - F::from_canonical_u32(dst), - digest.map(|b| F::from_canonical_u8(b)), - ); + let hash_result: HashResult; + if C::OPCODE_NAME == "SHA256" { + let hasher = Sha256::new(); + hash_result = + execute_hash::(hasher, num_blocks, src, len, dst, memory, e); + } else if C::OPCODE_NAME == "SHA512" { + let hasher = Sha512::new(); + hash_result = + execute_hash::(hasher, num_blocks, src, len, dst, memory, e); + } else { + panic!("Unsupported opcode: {}", C::OPCODE_NAME); + } - self.records.push(Sha256Record { + self.records.push(Sha2Record { from_state: from_state.map(F::from_canonical_u32), dst_read, src_read, len_read, - input_records, - input_message, - digest_write, + input_records: hash_result.input_records, + input_message: hash_result.input_message, + digest_writes: hash_result.digest_writes, }); Ok(ExecutionState { @@ -192,14 +161,130 @@ impl InstructionExecutor for Sha256VmChip { } fn get_opcode_name(&self, _: usize) -> String { - "SHA256".to_string() + C::OPCODE_NAME.to_string() + } +} + +struct HashResult { + input_records: Vec>, + input_message: Vec>>, + digest_writes: Vec, +} +fn execute_hash( + mut hasher: H, + num_blocks: usize, + src: u32, + len: u32, + dst: u32, + memory: &mut MemoryController, + address_space: F, +) -> HashResult { + let mut input_records: Vec> = Vec::with_capacity(num_blocks * C::NUM_READ_ROWS); + let mut input_message = Vec::with_capacity(num_blocks * C::NUM_READ_ROWS); + let mut read_ptr = src; + for _ in 0..num_blocks { + let block_reads_records = (0..C::NUM_READ_ROWS) + .map(|i| { + if C::OPCODE_NAME == "SHA256" { + let (id, data) = memory.read::<{ Sha256Config::READ_SIZE }>( + address_space, + F::from_canonical_u32(read_ptr + (i * C::READ_SIZE) as u32), + ); + (id, data.to_vec()) + } else if C::OPCODE_NAME == "SHA512" { + let (id, data) = memory.read::<{ Sha512Config::READ_SIZE }>( + address_space, + F::from_canonical_u32(read_ptr + (i * C::READ_SIZE) as u32), + ); + (id, data.to_vec()) + } else { + panic!("unsupported opcode: {}", C::OPCODE_NAME); + } + }) + .collect::>(); + let block_reads_bytes = (0..C::NUM_READ_ROWS) + .map(|i| { + // we add to the hasher only the bytes that are part of the message + let num_reads = min(C::READ_SIZE, (max(read_ptr, src + len) - read_ptr) as usize); + let row_input: &[u8] = &block_reads_records[i] + .1 + .iter() + .map(|x| x.as_canonical_u32().try_into().unwrap()) + .collect::>(); + hasher.update(&row_input[..num_reads]); + read_ptr += C::READ_SIZE as u32; + row_input.to_vec() + }) + .collect::>(); + input_records.push(block_reads_records.into_iter().map(|x| x.0).collect()); + input_message.push(block_reads_bytes); + } + + let mut digest = vec![0u8; C::DIGEST_SIZE]; + digest.copy_from_slice(hasher.finalize().as_ref()); + + match C::VARIANT { + Sha2Variant::Sha256 => { + debug_assert_eq!(C::NUM_WRITES, 1); + let (digest_write, _) = memory.write::<{ Sha256Config::DIGEST_SIZE }>( + address_space, + F::from_canonical_u32(dst), + digest + .iter() + .map(|b| F::from_canonical_u8(*b)) + .collect::>() + .try_into() + .unwrap(), + ); + HashResult { + input_records, + input_message, + digest_writes: vec![digest_write], + } + } + Sha2Variant::Sha512 => { + debug_assert_eq!(C::NUM_WRITES, 2); + // write the digest in two halves because we only support writes up to 32 bytes + let digest = digest + .iter() + .map(|b| F::from_canonical_u8(*b)) + .collect::>(); + let mut digest_writes = Vec::with_capacity(C::NUM_WRITES); + for i in 0..C::NUM_WRITES { + let (digest_write, _) = memory.write::<{ Sha512Config::WRITE_SIZE }>( + address_space, + F::from_canonical_usize(dst as usize + i * Sha512Config::WRITE_SIZE), + digest[i * Sha512Config::WRITE_SIZE..(i + 1) * Sha512Config::WRITE_SIZE] + .try_into() + .unwrap(), + ); + digest_writes.push(digest_write); + } + HashResult { + input_records, + input_message, + digest_writes, + } + } } } -pub fn sha256_solve(input_message: &[u8]) -> [u8; SHA256_WRITE_SIZE] { - let mut hasher = Sha256::new(); - hasher.update(input_message); - let mut output = [0u8; SHA256_WRITE_SIZE]; - output.copy_from_slice(hasher.finalize().as_ref()); - output +// Returns a Vec of length C::DIGEST_SIZE +pub fn sha2_solve(input_message: &[u8]) -> Vec { + match C::VARIANT { + Sha2Variant::Sha256 => { + let mut hasher = Sha256::new(); + hasher.update(input_message); + let mut output = vec![0u8; C::DIGEST_SIZE]; + output.copy_from_slice(hasher.finalize().as_ref()); + output + } + Sha2Variant::Sha512 => { + let mut hasher = Sha512::new(); + hasher.update(input_message); + let mut output = vec![0u8; C::DIGEST_SIZE]; + output.copy_from_slice(hasher.finalize().as_ref()); + output + } + } } diff --git a/extensions/sha256/circuit/src/sha256_chip/tests.rs b/extensions/sha256/circuit/src/sha256_chip/tests.rs index db6199c813..99181579b1 100644 --- a/extensions/sha256/circuit/src/sha256_chip/tests.rs +++ b/extensions/sha256/circuit/src/sha256_chip/tests.rs @@ -6,22 +6,22 @@ use openvm_circuit_primitives::bitwise_op_lookup::{ BitwiseOperationLookupBus, SharedBitwiseOperationLookupChip, }; use openvm_instructions::{instruction::Instruction, riscv::RV32_CELL_BITS, LocalOpcode}; -use openvm_sha256_transpiler::Rv32Sha256Opcode::{self, *}; -use openvm_sha_air::get_random_message; +use openvm_sha256_transpiler::Rv32Sha2Opcode::{self, *}; +use openvm_sha_air::{get_random_message, Sha256Config, Sha512Config}; 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}; -use super::Sha256VmChip; -use crate::{sha256_solve, Sha256VmDigestCols, Sha256VmRoundCols}; +use super::{Sha2VmChip, ShaChipConfig}; +use crate::{sha2_solve, ShaVmDigestColsRef, ShaVmRoundColsRef}; type F = BabyBear; const BUS_IDX: BusIndex = 28; -fn set_and_execute( +fn set_and_execute( tester: &mut VmChipTestBuilder, - chip: &mut Sha256VmChip, + chip: &mut Sha2VmChip, rng: &mut StdRng, - opcode: Rv32Sha256Opcode, + opcode: Rv32Sha2Opcode, message: Option<&[u8]>, len: Option, ) { @@ -40,7 +40,7 @@ fn set_and_execute( .borrow() .mem_config() .pointer_max_bits; - let dst_ptr = rng.gen_range(0..max_mem_ptr); + let dst_ptr = rng.gen_range(0..max_mem_ptr - C::DIGEST_SIZE as u32); let dst_ptr = dst_ptr ^ (dst_ptr & 3); tester.write(1, rd, dst_ptr.to_le_bytes().map(F::from_canonical_u8)); let src_ptr = rng.gen_range(0..(max_mem_ptr - len as u32)); @@ -57,11 +57,25 @@ fn set_and_execute( &Instruction::from_usize(opcode.global_opcode(), [rd, rs1, rs2, 1, 2]), ); - let output = sha256_solve(message); - assert_eq!( - output.map(F::from_canonical_u8), - tester.read::<32>(2, dst_ptr as usize) - ); + let output = sha2_solve::(message); + if C::OPCODE_NAME == "SHA256" { + assert_eq!( + output + .into_iter() + .map(F::from_canonical_u8) + .collect::>(), + tester.read::<{ Sha256Config::DIGEST_SIZE }>(2, dst_ptr as usize) + ); + } else if C::OPCODE_NAME == "SHA512" { + // TODO: break into two reads + assert_eq!( + output + .into_iter() + .map(F::from_canonical_u8) + .collect::>(), + tester.read::<{ Sha512Config::DIGEST_SIZE }>(2, dst_ptr as usize) + ); + } } /////////////////////////////////////////////////////////////////////////////////////// @@ -70,14 +84,13 @@ fn set_and_execute( /// Randomly generate computations and execute, ensuring that the generated trace /// passes all constraints. /////////////////////////////////////////////////////////////////////////////////////// -#[test] -fn rand_sha256_test() { +fn rand_sha_test(opcode: Rv32Sha2Opcode) { setup_tracing(); let mut rng = create_seeded_rng(); let mut tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); let bitwise_chip = SharedBitwiseOperationLookupChip::::new(bitwise_bus); - let mut chip = Sha256VmChip::new( + let mut chip = Sha2VmChip::::new( SystemPort { execution_bus: tester.execution_bus(), program_bus: tester.program_bus(), @@ -86,31 +99,40 @@ fn rand_sha256_test() { tester.address_bits(), bitwise_chip.clone(), BUS_IDX, - Rv32Sha256Opcode::CLASS_OFFSET, + Rv32Sha2Opcode::CLASS_OFFSET, tester.offline_memory_mutex_arc(), ); let num_tests: usize = 3; for _ in 0..num_tests { - set_and_execute(&mut tester, &mut chip, &mut rng, SHA256, None, None); + set_and_execute::(&mut tester, &mut chip, &mut rng, opcode, None, None); } let tester = tester.build().load(chip).load(bitwise_chip).finalize(); tester.simple_test().expect("Verification failed"); } +#[test] +fn rand_sha256_test() { + rand_sha_test::(SHA256); +} + +#[test] +fn rand_sha512_test() { + rand_sha_test::(SHA512); +} + /////////////////////////////////////////////////////////////////////////////////////// /// SANITY TESTS /// /// Ensure that solve functions produce the correct results. /////////////////////////////////////////////////////////////////////////////////////// -#[test] -fn execute_roundtrip_sanity_test() { +fn execute_roundtrip_sanity_test(opcode: Rv32Sha2Opcode) { let mut rng = create_seeded_rng(); let mut tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); let bitwise_chip = SharedBitwiseOperationLookupChip::::new(bitwise_bus); - let mut chip = Sha256VmChip::new( + let mut chip = Sha2VmChip::::new( SystemPort { execution_bus: tester.execution_bus(), program_bus: tester.program_bus(), @@ -119,28 +141,39 @@ fn execute_roundtrip_sanity_test() { tester.address_bits(), bitwise_chip.clone(), BUS_IDX, - Rv32Sha256Opcode::CLASS_OFFSET, + Rv32Sha2Opcode::CLASS_OFFSET, tester.offline_memory_mutex_arc(), ); println!( - "Sha256VmDigestCols::width(): {}", - Sha256VmDigestCols::::width() + "ShaVmDigestColsRef::::width::(): {}", + ShaVmDigestColsRef::::width::() ); println!( - "Sha256VmRoundCols::width(): {}", - Sha256VmRoundCols::::width() + "ShaVmRoundColsRef::::width::(): {}", + ShaVmRoundColsRef::::width::() ); + let num_tests: usize = 1; for _ in 0..num_tests { - set_and_execute(&mut tester, &mut chip, &mut rng, SHA256, None, None); + set_and_execute::(&mut tester, &mut chip, &mut rng, opcode, None, None); } } +#[test] +fn sha256_roundtrip_sanity_test() { + execute_roundtrip_sanity_test::(SHA256); +} + +#[test] +fn sha512_roundtrip_sanity_test() { + execute_roundtrip_sanity_test::(SHA512); +} + #[test] fn sha256_solve_sanity_check() { let input = b"Axiom is the best! Axiom is the best! Axiom is the best! Axiom is the best!"; - let output = sha256_solve(input); + let output = sha2_solve::(input); let expected: [u8; 32] = [ 99, 196, 61, 185, 226, 212, 131, 80, 154, 248, 97, 108, 157, 55, 200, 226, 160, 73, 207, 46, 245, 169, 94, 255, 42, 136, 193, 15, 40, 133, 173, 22, diff --git a/extensions/sha256/circuit/src/sha256_chip/trace.rs b/extensions/sha256/circuit/src/sha256_chip/trace.rs index 746385f16a..26474f9a32 100644 --- a/extensions/sha256/circuit/src/sha256_chip/trace.rs +++ b/extensions/sha256/circuit/src/sha256_chip/trace.rs @@ -1,12 +1,10 @@ -use std::{array, borrow::BorrowMut, sync::Arc}; +use std::{borrow::BorrowMut, sync::Arc}; +use openvm_circuit::system::memory::offline_checker::MemoryWriteAuxCols; 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_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, -}; +use openvm_sha_air::{get_flag_pt_array, limbs_into_word, Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{ config::{StarkGenericConfig, Val}, p3_air::BaseAir, @@ -18,16 +16,10 @@ use openvm_stark_backend::{ AirRef, Chip, ChipUsageGetter, }; -use super::{ - Sha256VmChip, Sha256VmDigestCols, Sha256VmRoundCols, SHA256VM_CONTROL_WIDTH, - SHA256VM_DIGEST_WIDTH, SHA256VM_ROUND_WIDTH, -}; -use crate::{ - sha256_chip::{PaddingFlags, SHA256_READ_SIZE}, - SHA256_BLOCK_CELLS, -}; +use super::{Sha2Variant, Sha2VmChip, ShaChipConfig, ShaVmDigestColsRefMut, ShaVmRoundColsRefMut}; +use crate::sha256_chip::PaddingFlags; -impl Chip for Sha256VmChip> +impl Chip for Sha2VmChip, C> where Val: PrimeField32, { @@ -50,7 +42,7 @@ where let mem_ptr_shift: u32 = 1 << (RV32_REGISTER_NUM_LIMBS * RV32_CELL_BITS - self.air.ptr_max_bits); - let mut states = Vec::with_capacity(height.div_ceil(SHA256_ROWS_PER_BLOCK)); + let mut states = Vec::with_capacity(height.div_ceil(C::ROWS_PER_BLOCK)); let mut global_block_idx = 0; for (record_idx, record) in records.iter().enumerate() { let dst_read = offline_memory.record_by_id(record.dst_read); @@ -70,13 +62,7 @@ where let len = compose(len_read.data_slice().try_into().unwrap()); let mut state = &None; for (i, input_message) in record.input_message.iter().enumerate() { - let input_message = input_message - .iter() - .flatten() - .copied() - .collect::>() - .try_into() - .unwrap(); + let input_message = input_message.iter().flatten().copied().collect::>(); states.push(Some(Self::generate_state( state, input_message, @@ -89,151 +75,273 @@ where } } states.extend( - std::iter::repeat(None) - .take((height - non_padded_height).div_ceil(SHA256_ROWS_PER_BLOCK)), + std::iter::repeat(None).take((height - non_padded_height).div_ceil(C::ROWS_PER_BLOCK)), ); // During the first pass we will fill out most of the matrix // But there are some cells that can't be generated by the first pass so we will do a second pass over the matrix values - .par_chunks_mut(width * SHA256_ROWS_PER_BLOCK) + .par_chunks_mut(width * C::ROWS_PER_BLOCK) .zip(states.into_par_iter().enumerate()) .for_each(|(block, (global_block_idx, state))| { // Fill in a valid block if let Some(state) = state { let mut has_padding_occurred = - state.local_block_idx * SHA256_BLOCK_CELLS > state.message_len as usize; + state.local_block_idx * C::BLOCK_CELLS > state.message_len as usize; let message_left = if has_padding_occurred { 0 } else { - state.message_len as usize - state.local_block_idx * SHA256_BLOCK_CELLS + state.message_len as usize - state.local_block_idx * C::BLOCK_CELLS }; let is_last_block = state.is_last_block; - let buffer: [[Val; SHA256_BUFFER_SIZE]; 4] = array::from_fn(|j| { - array::from_fn(|k| { - Val::::from_canonical_u8( - state.block_input_message[j * SHA256_BUFFER_SIZE + k], - ) + let buffer: Vec>> = (0..C::MESSAGE_ROWS) + .map(|j| { + (0..C::CELLS_PER_ROW) + .map(|k| { + Val::::from_canonical_u8( + state.block_input_message[j * C::CELLS_PER_ROW + k], + ) + }) + .collect::>() }) - }); + .collect::>(); - let padded_message: [u32; SHA256_BLOCK_WORDS] = array::from_fn(|j| { - limbs_into_u32::(array::from_fn(|k| { - state.block_padded_message[(j + 1) * SHA256_WORD_U8S - k - 1] as u32 - })) - }); + let padded_message: Vec = (0..C::BLOCK_WORDS) + .map(|j| { + limbs_into_word::( + &(0..C::WORD_U8S) + .map(|k| { + state.block_padded_message[(j + 1) * C::WORD_U8S - k - 1] + as u32 + }) + .collect::>(), + ) + }) + .collect::>(); - self.air.sha256_subair.generate_block_trace::>( + self.air.sha_subair.generate_block_trace::>( block, width, - SHA256VM_CONTROL_WIDTH, + C::VM_CONTROL_WIDTH, &padded_message, self.bitwise_lookup_chip.clone(), &state.hash, is_last_block, global_block_idx as u32 + 1, state.local_block_idx as u32, - &buffer, + buffer, ); let block_reads = records[state.message_idx].input_records [state.local_block_idx] - .map(|record_id| offline_memory.record_by_id(record_id)); + .iter() + .map(|record_id| offline_memory.record_by_id(*record_id)) + .collect::>(); let mut read_ptr = block_reads[0].pointer; let mut cur_timestamp = Val::::from_canonical_u32(block_reads[0].timestamp); - let read_size = Val::::from_canonical_usize(SHA256_READ_SIZE); - for row in 0..SHA256_ROWS_PER_BLOCK { + let read_size = Val::::from_canonical_usize(C::READ_SIZE); + for row in 0..C::ROWS_PER_BLOCK { let row_slice = &mut block[row * width..(row + 1) * width]; - if row < 16 { - let cols: &mut Sha256VmRoundCols> = - row_slice[..SHA256VM_ROUND_WIDTH].borrow_mut(); - cols.control.len = Val::::from_canonical_u32(state.message_len); - cols.control.read_ptr = read_ptr; - cols.control.cur_timestamp = cur_timestamp; - if row < 4 { + if row < C::ROUND_ROWS { + let mut cols = ShaVmRoundColsRefMut::from::( + row_slice[..C::VM_ROUND_WIDTH].borrow_mut(), + ); + *cols.control.len = Val::::from_canonical_u32(state.message_len); + *cols.control.read_ptr = read_ptr; + *cols.control.cur_timestamp = cur_timestamp; + if row < C::MESSAGE_ROWS { read_ptr += read_size; cur_timestamp += Val::::ONE; memory_aux_cols_factory - .generate_read_aux(block_reads[row], &mut cols.read_aux); + .generate_read_aux(block_reads[row], cols.read_aux); - if (row + 1) * SHA256_READ_SIZE <= message_left { - cols.control.pad_flags = get_flag_pt_array( - &self.air.padding_encoder, - PaddingFlags::NotPadding as usize, - ) - .map(Val::::from_canonical_u32); + if (row + 1) * C::READ_SIZE <= message_left { + cols.control + .pad_flags + .iter_mut() + .zip( + get_flag_pt_array( + &self.air.padding_encoder, + PaddingFlags::NotPadding as usize, + ) + .into_iter() + .map(Val::::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); } else if !has_padding_occurred { has_padding_occurred = true; - let len = message_left - row * SHA256_READ_SIZE; - cols.control.pad_flags = get_flag_pt_array( - &self.air.padding_encoder, - if row == 3 && is_last_block { - PaddingFlags::FirstPadding0_LastRow - } else { - PaddingFlags::FirstPadding0 - } as usize - + len, - ) - .map(Val::::from_canonical_u32); + let len = message_left - row * C::READ_SIZE; + cols.control + .pad_flags + .iter_mut() + .zip( + get_flag_pt_array( + &self.air.padding_encoder, + if row == 3 && is_last_block { + PaddingFlags::FirstPadding0_LastRow + } else { + PaddingFlags::FirstPadding0 + } + as usize + + len, + ) + .into_iter() + .map(Val::::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); } else { - cols.control.pad_flags = get_flag_pt_array( - &self.air.padding_encoder, - if row == 3 && is_last_block { - PaddingFlags::EntirePaddingLastRow - } else { - PaddingFlags::EntirePadding - } as usize, - ) - .map(Val::::from_canonical_u32); + cols.control + .pad_flags + .iter_mut() + .zip( + get_flag_pt_array( + &self.air.padding_encoder, + if row == 3 && is_last_block { + PaddingFlags::EntirePaddingLastRow + } else { + PaddingFlags::EntirePadding + } + as usize, + ) + .into_iter() + .map(Val::::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); } } else { - cols.control.pad_flags = get_flag_pt_array( - &self.air.padding_encoder, - PaddingFlags::NotConsidered as usize, - ) - .map(Val::::from_canonical_u32); + cols.control + .pad_flags + .iter_mut() + .zip( + get_flag_pt_array( + &self.air.padding_encoder, + PaddingFlags::NotConsidered as usize, + ) + .into_iter() + .map(Val::::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); } - cols.control.padding_occurred = + *cols.control.padding_occurred = Val::::from_bool(has_padding_occurred); } else { if is_last_block { has_padding_occurred = false; } - let cols: &mut Sha256VmDigestCols> = - row_slice[..SHA256VM_DIGEST_WIDTH].borrow_mut(); - cols.control.len = Val::::from_canonical_u32(state.message_len); - cols.control.read_ptr = read_ptr; - cols.control.cur_timestamp = cur_timestamp; - cols.control.pad_flags = get_flag_pt_array( - &self.air.padding_encoder, - PaddingFlags::NotConsidered as usize, - ) - .map(Val::::from_canonical_u32); + let mut cols = ShaVmDigestColsRefMut::from::( + row_slice[..C::VM_DIGEST_WIDTH].borrow_mut(), + ); + *cols.control.len = Val::::from_canonical_u32(state.message_len); + *cols.control.read_ptr = read_ptr; + *cols.control.cur_timestamp = cur_timestamp; + cols.control + .pad_flags + .iter_mut() + .zip( + get_flag_pt_array( + &self.air.padding_encoder, + PaddingFlags::NotConsidered as usize, + ) + .into_iter() + .map(Val::::from_canonical_u32), + ) + .for_each(|(x, y)| *x = y); if is_last_block { let record = &records[state.message_idx]; let dst_read = offline_memory.record_by_id(record.dst_read); let src_read = offline_memory.record_by_id(record.src_read); let len_read = offline_memory.record_by_id(record.len_read); - let digest_write = offline_memory.record_by_id(record.digest_write); - cols.from_state = record.from_state; - cols.rd_ptr = dst_read.pointer; - cols.rs1_ptr = src_read.pointer; - cols.rs2_ptr = len_read.pointer; - cols.dst_ptr.copy_from_slice(dst_read.data_slice()); - cols.src_ptr.copy_from_slice(src_read.data_slice()); - cols.len_data.copy_from_slice(len_read.data_slice()); - memory_aux_cols_factory - .generate_read_aux(dst_read, &mut cols.register_reads_aux[0]); + let digest_writes: Vec<_> = record + .digest_writes + .iter() + .map(|id| offline_memory.record_by_id(*id)) + .collect(); + *cols.from_state = record.from_state; + *cols.rd_ptr = dst_read.pointer; + *cols.rs1_ptr = src_read.pointer; + *cols.rs2_ptr = len_read.pointer; + cols.dst_ptr + .iter_mut() + .zip(dst_read.data_slice()) + .for_each(|(x, y)| *x = *y); + cols.src_ptr + .iter_mut() + .zip(src_read.data_slice()) + .for_each(|(x, y)| *x = *y); + cols.len_data + .iter_mut() + .zip(len_read.data_slice()) + .for_each(|(x, y)| *x = *y); + memory_aux_cols_factory.generate_read_aux( + dst_read, + cols.register_reads_aux.get_mut(0).unwrap(), + ); memory_aux_cols_factory .generate_read_aux(src_read, &mut cols.register_reads_aux[1]); memory_aux_cols_factory .generate_read_aux(len_read, &mut cols.register_reads_aux[2]); - memory_aux_cols_factory - .generate_write_aux(digest_write, &mut cols.writes_aux); + + match C::VARIANT { + Sha2Variant::Sha256 => { + debug_assert_eq!(C::NUM_WRITES, 1); + debug_assert_eq!(digest_writes.len(), 1); + debug_assert_eq!(cols.writes_aux_base.len(), 1); + debug_assert_eq!(cols.writes_aux_prev_data.nrows(), 1); + let digest_write = digest_writes[0]; + // write to a temporary MemoryWriteAuxCols object and then copy it over to the columns struct. + let mut writes_aux: MemoryWriteAuxCols< + Val, + { Sha256Config::DIGEST_SIZE }, + > = MemoryWriteAuxCols::from_base( + cols.writes_aux_base[0], + cols.writes_aux_prev_data + .row(0) + .to_vec() + .try_into() + .unwrap(), + ); + memory_aux_cols_factory + .generate_write_aux(digest_write, &mut writes_aux); + cols.writes_aux_base[0] = writes_aux.get_base(); + cols.writes_aux_prev_data + .row_mut(0) + .iter_mut() + .zip(writes_aux.prev_data()) + .for_each(|(x, y)| *x = *y); + } + Sha2Variant::Sha512 => { + debug_assert_eq!(C::NUM_WRITES, 2); + debug_assert_eq!(digest_writes.len(), 2); + debug_assert_eq!(cols.writes_aux_base.len(), 2); + debug_assert_eq!(cols.writes_aux_prev_data.nrows(), 2); + for i in 0..C::NUM_WRITES { + let prev_data = + cols.writes_aux_prev_data.row(i).to_vec(); + // write to a temporary MemoryWriteAuxCols object and then copy it over to the columns struct + let mut writes_aux: MemoryWriteAuxCols< + Val, + { Sha512Config::WRITE_SIZE }, + > = MemoryWriteAuxCols::from_base( + cols.writes_aux_base[i], + prev_data.try_into().unwrap(), + ); + memory_aux_cols_factory.generate_write_aux( + digest_writes[i], + &mut writes_aux, + ); + cols.writes_aux_base[i] = writes_aux.get_base(); + cols.writes_aux_prev_data + .row_mut(i) + .iter_mut() + .zip(writes_aux.prev_data()) + .for_each(|(x, y)| *x = *y); + } + } + } } - cols.control.padding_occurred = + *cols.control.padding_occurred = Val::::from_bool(has_padding_occurred); } } @@ -241,8 +349,8 @@ where // Fill in the invalid rows else { block.par_chunks_mut(width).for_each(|row| { - let cols: &mut Sha256VmRoundCols> = row.borrow_mut(); - self.air.sha256_subair.generate_default_row(&mut cols.inner); + let cols = ShaVmRoundColsRefMut::from::(row.borrow_mut()); + self.air.sha_subair.generate_default_row(cols.inner); }) } }); @@ -250,25 +358,25 @@ where // Do a second pass over the trace to fill in the missing values // Note, we need to skip the very first row 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 - .sha256_subair - .generate_missing_cells(chunk, width, SHA256VM_CONTROL_WIDTH); + .sha_subair + .generate_missing_cells(chunk, width, C::VM_CONTROL_WIDTH); }); AirProofInput::simple_no_pis(RowMajorMatrix::new(values, width)) } } -impl ChipUsageGetter for Sha256VmChip { +impl ChipUsageGetter for Sha2VmChip { fn air_name(&self) -> String { get_air_name(&self.air) } fn current_trace_height(&self) -> usize { self.records.iter().fold(0, |acc, record| { - acc + record.input_records.len() * SHA256_ROWS_PER_BLOCK + acc + record.input_records.len() * C::ROWS_PER_BLOCK }) } @@ -279,55 +387,61 @@ impl ChipUsageGetter for Sha256VmChip { /// This is the state information that a block will use to generate its trace #[derive(Debug, Clone)] -struct Sha256State { - hash: [u32; SHA256_HASH_WORDS], +struct Sha2State { + hash: Vec, // length should be C::HASH_WORDS local_block_idx: usize, message_len: u32, - block_input_message: [u8; SHA256_BLOCK_CELLS], - block_padded_message: [u8; SHA256_BLOCK_CELLS], + block_input_message: Vec, // length should be C::BLOCK_CELLS + block_padded_message: Vec, // length should be C::BLOCK_CELLS message_idx: usize, is_last_block: bool, } -impl Sha256VmChip { +impl Sha2VmChip { fn generate_state( - prev_state: &Option, - block_input_message: [u8; SHA256_BLOCK_CELLS], + prev_state: &Option>, + block_input_message: Vec, // length should be C::BLOCK_CELLS message_idx: usize, message_len: u32, is_last_block: bool, - ) -> Sha256State { + ) -> Sha2State { + debug_assert_eq!(block_input_message.len(), C::BLOCK_CELLS); let local_block_idx = if let Some(prev_state) = prev_state { prev_state.local_block_idx + 1 } else { 0 }; - let has_padding_occurred = local_block_idx * SHA256_BLOCK_CELLS > message_len as usize; + let has_padding_occurred = local_block_idx * C::BLOCK_CELLS > message_len as usize; let message_left = if has_padding_occurred { 0 } else { - message_len as usize - local_block_idx * SHA256_BLOCK_CELLS + message_len as usize - local_block_idx * C::BLOCK_CELLS }; - let padded_message_bytes: [u8; SHA256_BLOCK_CELLS] = array::from_fn(|j| { - if j < message_left { - block_input_message[j] - } else if j == message_left && !has_padding_occurred { - 1 << (RV32_CELL_BITS - 1) - } else if !is_last_block || j < SHA256_BLOCK_CELLS - 4 { - 0u8 - } else { - let shift_amount = (SHA256_BLOCK_CELLS - j - 1) * RV32_CELL_BITS; - ((message_len * RV32_CELL_BITS as u32) - .checked_shr(shift_amount as u32) - .unwrap_or(0) - & ((1 << RV32_CELL_BITS) - 1)) as u8 - } - }); + let padded_message_bytes: Vec = (0..C::BLOCK_CELLS) + .map(|j| { + if j < message_left { + block_input_message[j] + } else if j == message_left && !has_padding_occurred { + 1 << (RV32_CELL_BITS - 1) + } else if !is_last_block || j < C::BLOCK_CELLS - 4 { + 0u8 + } else { + let shift_amount = (C::BLOCK_CELLS - j - 1) * RV32_CELL_BITS; + ((message_len * RV32_CELL_BITS as u32) + .checked_shr(shift_amount as u32) + .unwrap_or(0) + & ((1 << RV32_CELL_BITS) - 1)) as u8 + } + }) + .collect(); if let Some(prev_state) = prev_state { - Sha256State { - hash: Sha256Air::get_block_hash(&prev_state.hash, prev_state.block_padded_message), + Sha2State { + hash: Sha2Air::::get_block_hash( + &prev_state.hash, + prev_state.block_padded_message.clone(), + ), local_block_idx, message_len, block_input_message, @@ -336,8 +450,8 @@ impl Sha256VmChip { is_last_block, } } else { - Sha256State { - hash: SHA256_H, + Sha2State { + hash: C::get_h().to_vec(), local_block_idx: 0, message_len, block_input_message, diff --git a/extensions/sha256/circuit/tmp.rs b/extensions/sha256/circuit/tmp.rs new file mode 100644 index 0000000000..d2f2e9def5 --- /dev/null +++ b/extensions/sha256/circuit/tmp.rs @@ -0,0 +1,585 @@ +#[derive(Clone)] +pub struct ShaVmRoundColsRef<'a, T> { + pub control: ShaVmControlColsRef<'a, T>, + pub inner: ShaRoundColsRef<'a, T>, + pub read_aux: &'a MemoryReadAuxCols, +} +impl<'a, T> ShaVmRoundColsRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let control_length = >::width::(); + let (control_slice, slice) = slice.split_at(control_length); + let control_slice = >::from::(control_slice); + let inner_length = >::width::(); + let (inner_slice, slice) = slice.split_at(inner_length); + let inner_slice = >::from::(inner_slice); + let read_aux_length = >::width(); + let (read_aux_slice, slice) = slice.split_at(read_aux_length); + Self { + control: control_slice, + inner: inner_slice, + read_aux: { + use core::borrow::Borrow; + read_aux_slice.borrow() + }, + } + } + pub const fn width() -> usize { + 0 + >::width::() + + >::width::() + + >::width() + } +} +impl<'b, T> ShaVmRoundColsRef<'b, T> { + pub fn from_mut<'a, C: ShaChipConfig>(other: &'b ShaVmRoundColsRefMut<'a, T>) -> Self { + Self { + control: >::from_mut::(&other.control), + inner: >::from_mut::(&other.inner), + read_aux: other.read_aux, + } + } +} +pub struct ShaVmRoundColsRefMut<'a, T> { + pub control: ShaVmControlColsRefMut<'a, T>, + pub inner: ShaRoundColsRefMut<'a, T>, + pub read_aux: &'a mut MemoryReadAuxCols, +} +impl<'a, T> ShaVmRoundColsRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let control_length = >::width::(); + let (control_slice, slice) = slice.split_at_mut(control_length); + let control_slice = >::from::(control_slice); + let inner_length = >::width::(); + let (inner_slice, slice) = slice.split_at_mut(inner_length); + let inner_slice = >::from::(inner_slice); + let read_aux_length = >::width(); + let (read_aux_slice, slice) = slice.split_at_mut(read_aux_length); + Self { + control: control_slice, + inner: inner_slice, + read_aux: { + use core::borrow::BorrowMut; + read_aux_slice.borrow_mut() + }, + } + } + pub const fn width() -> usize { + 0 + >::width::() + + >::width::() + + >::width() + } +} +#[derive(Clone)] +pub struct ShaVmDigestColsRef<'a, T> { + pub control: ShaVmControlColsRef<'a, T>, + pub inner: ShaDigestColsRef<'a, T>, + pub from_state: &'a ExecutionState, + pub rd_ptr: &'a T, + pub rs1_ptr: &'a T, + pub rs2_ptr: &'a T, + pub dst_ptr: ndarray::ArrayView1<'a, T>, + pub src_ptr: ndarray::ArrayView1<'a, T>, + pub len_data: ndarray::ArrayView1<'a, T>, + pub register_reads_aux: ndarray::ArrayView1<'a, MemoryReadAuxCols>, + pub writes_aux_base: &'a MemoryBaseAuxCols, + pub writes_aux_prev_data: ndarray::ArrayView1<'a, T>, +} +impl<'a, T> ShaVmDigestColsRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let control_length = >::width::(); + let (control_slice, slice) = slice.split_at(control_length); + let control_slice = >::from::(control_slice); + let inner_length = >::width::(); + let (inner_slice, slice) = slice.split_at(inner_length); + let inner_slice = >::from::(inner_slice); + let from_state_length = >::width(); + let (from_state_slice, slice) = slice.split_at(from_state_length); + let rd_ptr_length = 1; + let (rd_ptr_slice, slice) = slice.split_at(rd_ptr_length); + let rs1_ptr_length = 1; + let (rs1_ptr_slice, slice) = slice.split_at(rs1_ptr_length); + let rs2_ptr_length = 1; + let (rs2_ptr_slice, slice) = slice.split_at(rs2_ptr_length); + let (dst_ptr_slice, slice) = slice.split_at(1 * RV32_REGISTER_NUM_LIMBS); + let dst_ptr_slice = + ndarray::ArrayView1::from_shape((RV32_REGISTER_NUM_LIMBS), dst_ptr_slice).unwrap(); + let (src_ptr_slice, slice) = slice.split_at(1 * RV32_REGISTER_NUM_LIMBS); + let src_ptr_slice = + ndarray::ArrayView1::from_shape((RV32_REGISTER_NUM_LIMBS), src_ptr_slice).unwrap(); + let (len_data_slice, slice) = slice.split_at(1 * RV32_REGISTER_NUM_LIMBS); + let len_data_slice = + ndarray::ArrayView1::from_shape((RV32_REGISTER_NUM_LIMBS), len_data_slice).unwrap(); + let (register_reads_aux_slice, slice) = + slice.split_at(>::width() * SHA_REGISTER_READS); + let register_reads_aux_slice: &[MemoryReadAuxCols] = + unsafe { &*(slice as *const [T] as *const [MemoryReadAuxCols]) }; + let register_reads_aux_slice = + ndarray::ArrayView1::from_shape((SHA_REGISTER_READS), register_reads_aux_slice) + .unwrap(); + let writes_aux_base_length = >::width(); + let (writes_aux_base_slice, slice) = slice.split_at(writes_aux_base_length); + let (writes_aux_prev_data_slice, slice) = slice.split_at(1 * C::WRITE_SIZE); + let writes_aux_prev_data_slice = + ndarray::ArrayView1::from_shape((C::WRITE_SIZE), writes_aux_prev_data_slice).unwrap(); + Self { + control: control_slice, + inner: inner_slice, + from_state: { + use core::borrow::Borrow; + from_state_slice.borrow() + }, + rd_ptr: &rd_ptr_slice[0], + rs1_ptr: &rs1_ptr_slice[0], + rs2_ptr: &rs2_ptr_slice[0], + dst_ptr: dst_ptr_slice, + src_ptr: src_ptr_slice, + len_data: len_data_slice, + register_reads_aux: register_reads_aux_slice, + writes_aux_base: { + use core::borrow::Borrow; + writes_aux_base_slice.borrow() + }, + writes_aux_prev_data: writes_aux_prev_data_slice, + } + } + pub const fn width() -> usize { + 0 + >::width::() + + >::width::() + + >::width() + + 1 + + 1 + + 1 + + 1 * RV32_REGISTER_NUM_LIMBS + + 1 * RV32_REGISTER_NUM_LIMBS + + 1 * RV32_REGISTER_NUM_LIMBS + + >::width() * SHA_REGISTER_READS + + >::width() + + 1 * C::WRITE_SIZE + } +} +impl<'b, T> ShaVmDigestColsRef<'b, T> { + pub fn from_mut<'a, C: ShaChipConfig>(other: &'b ShaVmDigestColsRefMut<'a, T>) -> Self { + Self { + control: >::from_mut::(&other.control), + inner: >::from_mut::(&other.inner), + from_state: other.from_state, + rd_ptr: &other.rd_ptr, + rs1_ptr: &other.rs1_ptr, + rs2_ptr: &other.rs2_ptr, + dst_ptr: other.dst_ptr.view(), + src_ptr: other.src_ptr.view(), + len_data: other.len_data.view(), + register_reads_aux: other.register_reads_aux.view(), + writes_aux_base: other.writes_aux_base, + writes_aux_prev_data: other.writes_aux_prev_data.view(), + } + } +} +pub struct ShaVmDigestColsRefMut<'a, T> { + pub control: ShaVmControlColsRefMut<'a, T>, + pub inner: ShaDigestColsRefMut<'a, T>, + pub from_state: &'a mut ExecutionState, + pub rd_ptr: &'a mut T, + pub rs1_ptr: &'a mut T, + pub rs2_ptr: &'a mut T, + pub dst_ptr: ndarray::ArrayViewMut1<'a, T>, + pub src_ptr: ndarray::ArrayViewMut1<'a, T>, + pub len_data: ndarray::ArrayViewMut1<'a, T>, + pub register_reads_aux: ndarray::ArrayViewMut1<'a, MemoryReadAuxCols>, + pub writes_aux_base: &'a mut MemoryBaseAuxCols, + pub writes_aux_prev_data: ndarray::ArrayViewMut1<'a, T>, +} +impl<'a, T> ShaVmDigestColsRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let control_length = >::width::(); + let (control_slice, slice) = slice.split_at_mut(control_length); + let control_slice = >::from::(control_slice); + let inner_length = >::width::(); + let (inner_slice, slice) = slice.split_at_mut(inner_length); + let inner_slice = >::from::(inner_slice); + let from_state_length = >::width(); + let (from_state_slice, slice) = slice.split_at_mut(from_state_length); + let rd_ptr_length = 1; + let (rd_ptr_slice, slice) = slice.split_at_mut(rd_ptr_length); + let rs1_ptr_length = 1; + let (rs1_ptr_slice, slice) = slice.split_at_mut(rs1_ptr_length); + let rs2_ptr_length = 1; + let (rs2_ptr_slice, slice) = slice.split_at_mut(rs2_ptr_length); + let (dst_ptr_slice, slice) = slice.split_at_mut(1 * RV32_REGISTER_NUM_LIMBS); + let dst_ptr_slice = + ndarray::ArrayViewMut1::from_shape((RV32_REGISTER_NUM_LIMBS), dst_ptr_slice).unwrap(); + let (src_ptr_slice, slice) = slice.split_at_mut(1 * RV32_REGISTER_NUM_LIMBS); + let src_ptr_slice = + ndarray::ArrayViewMut1::from_shape((RV32_REGISTER_NUM_LIMBS), src_ptr_slice).unwrap(); + let (len_data_slice, slice) = slice.split_at_mut(1 * RV32_REGISTER_NUM_LIMBS); + let len_data_slice = + ndarray::ArrayViewMut1::from_shape((RV32_REGISTER_NUM_LIMBS), len_data_slice).unwrap(); + let (register_reads_aux_slice, slice) = + slice.split_at_mut(>::width() * SHA_REGISTER_READS); + let register_reads_aux_slice: &mut [MemoryReadAuxCols] = + unsafe { &mut *(slice as *mut [T] as *mut [MemoryReadAuxCols]) }; + let register_reads_aux_slice = + ndarray::ArrayViewMut1::from_shape((SHA_REGISTER_READS), register_reads_aux_slice) + .unwrap(); + let writes_aux_base_length = >::width(); + let (writes_aux_base_slice, slice) = slice.split_at_mut(writes_aux_base_length); + let (writes_aux_prev_data_slice, slice) = slice.split_at_mut(1 * C::WRITE_SIZE); + let writes_aux_prev_data_slice = + ndarray::ArrayViewMut1::from_shape((C::WRITE_SIZE), writes_aux_prev_data_slice) + .unwrap(); + Self { + control: control_slice, + inner: inner_slice, + from_state: { + use core::borrow::BorrowMut; + from_state_slice.borrow_mut() + }, + rd_ptr: &mut rd_ptr_slice[0], + rs1_ptr: &mut rs1_ptr_slice[0], + rs2_ptr: &mut rs2_ptr_slice[0], + dst_ptr: dst_ptr_slice, + src_ptr: src_ptr_slice, + len_data: len_data_slice, + register_reads_aux: register_reads_aux_slice, + writes_aux_base: { + use core::borrow::BorrowMut; + writes_aux_base_slice.borrow_mut() + }, + writes_aux_prev_data: writes_aux_prev_data_slice, + } + } + pub const fn width() -> usize { + 0 + >::width::() + + >::width::() + + >::width() + + 1 + + 1 + + 1 + + 1 * RV32_REGISTER_NUM_LIMBS + + 1 * RV32_REGISTER_NUM_LIMBS + + 1 * RV32_REGISTER_NUM_LIMBS + + >::width() * SHA_REGISTER_READS + + >::width() + + 1 * C::WRITE_SIZE + } +} +impl< + 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, + const WRITE_SIZE: usize, + > + core::borrow::Borrow< + ShaVmDigestCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + >, + > for [T] +{ + fn borrow( + &self, + ) -> &ShaVmDigestCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + > { + if true { + match ( + &self.len(), + &ShaVmDigestCols::< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + >::width(), + ) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + } + let (prefix, shorts, _suffix) = unsafe { + self.align_to::>() + }; + if true { + if !prefix.is_empty() { + { + ::core::panicking::panic_fmt(format_args!("Alignment should match")); + } + } + } + if true { + match (&shorts.len(), &1) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + } + &shorts[0] + } +} +impl< + 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, + const WRITE_SIZE: usize, + > + core::borrow::BorrowMut< + ShaVmDigestCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + >, + > for [T] +{ + fn borrow_mut( + &mut self, + ) -> &mut ShaVmDigestCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + > { + if true { + match ( + &self.len(), + &ShaVmDigestCols::< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + >::width(), + ) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + } + let (prefix, shorts, _suffix) = unsafe { + self.align_to_mut::>() + }; + if true { + if !prefix.is_empty() { + { + ::core::panicking::panic_fmt(format_args!("Alignment should match")); + } + } + } + if true { + match (&shorts.len(), &1) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + } + &mut shorts[0] + } +} +impl< + 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, + const WRITE_SIZE: usize, + > + ShaVmDigestCols< + T, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + > +{ + pub const fn width() -> usize { + std::mem::size_of::< + ShaVmDigestCols< + u8, + WORD_BITS, + WORD_U8S, + WORD_U16S, + HASH_WORDS, + ROUNDS_PER_ROW, + ROUNDS_PER_ROW_MINUS_ONE, + ROW_VAR_CNT, + WRITE_SIZE, + >, + >() + } +} +#[derive(Clone)] +pub struct ShaVmControlColsRef<'a, T> { + pub len: &'a T, + pub cur_timestamp: &'a T, + pub read_ptr: &'a T, + pub pad_flags: ndarray::ArrayView1<'a, T>, + pub padding_occurred: &'a T, +} +impl<'a, T> ShaVmControlColsRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let len_length = 1; + let (len_slice, slice) = slice.split_at(len_length); + let cur_timestamp_length = 1; + let (cur_timestamp_slice, slice) = slice.split_at(cur_timestamp_length); + let read_ptr_length = 1; + let (read_ptr_slice, slice) = slice.split_at(read_ptr_length); + let (pad_flags_slice, slice) = slice.split_at(1 * 6); + let pad_flags_slice = ndarray::ArrayView1::from_shape((6), pad_flags_slice).unwrap(); + let padding_occurred_length = 1; + let (padding_occurred_slice, slice) = slice.split_at(padding_occurred_length); + Self { + len: &len_slice[0], + cur_timestamp: &cur_timestamp_slice[0], + read_ptr: &read_ptr_slice[0], + pad_flags: pad_flags_slice, + padding_occurred: &padding_occurred_slice[0], + } + } + pub const fn width() -> usize { + 0 + 1 + 1 + 1 + 1 * 6 + 1 + } +} +impl<'b, T> ShaVmControlColsRef<'b, T> { + pub fn from_mut<'a, C: ShaChipConfig>(other: &'b ShaVmControlColsRefMut<'a, T>) -> Self { + Self { + len: &other.len, + cur_timestamp: &other.cur_timestamp, + read_ptr: &other.read_ptr, + pad_flags: other.pad_flags.view(), + padding_occurred: &other.padding_occurred, + } + } +} +pub struct ShaVmControlColsRefMut<'a, T> { + pub len: &'a mut T, + pub cur_timestamp: &'a mut T, + pub read_ptr: &'a mut T, + pub pad_flags: ndarray::ArrayViewMut1<'a, T>, + pub padding_occurred: &'a mut T, +} +impl<'a, T> ShaVmControlColsRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let len_length = 1; + let (len_slice, slice) = slice.split_at_mut(len_length); + let cur_timestamp_length = 1; + let (cur_timestamp_slice, slice) = slice.split_at_mut(cur_timestamp_length); + let read_ptr_length = 1; + let (read_ptr_slice, slice) = slice.split_at_mut(read_ptr_length); + let (pad_flags_slice, slice) = slice.split_at_mut(1 * 6); + let pad_flags_slice = ndarray::ArrayViewMut1::from_shape((6), pad_flags_slice).unwrap(); + let padding_occurred_length = 1; + let (padding_occurred_slice, slice) = slice.split_at_mut(padding_occurred_length); + Self { + len: &mut len_slice[0], + cur_timestamp: &mut cur_timestamp_slice[0], + read_ptr: &mut read_ptr_slice[0], + pad_flags: pad_flags_slice, + padding_occurred: &mut padding_occurred_slice[0], + } + } + pub const fn width() -> usize { + 0 + 1 + 1 + 1 + 1 * 6 + 1 + } +} diff --git a/extensions/sha256/guest/src/lib.rs b/extensions/sha256/guest/src/lib.rs index cb34bcd5aa..53b60e8bc3 100644 --- a/extensions/sha256/guest/src/lib.rs +++ b/extensions/sha256/guest/src/lib.rs @@ -2,8 +2,14 @@ /// This is custom-0 defined in RISC-V spec document pub const OPCODE: u8 = 0x0b; -pub const SHA256_FUNCT3: u8 = 0b100; -pub const SHA256_FUNCT7: u8 = 0x1; +pub const SHA2_FUNCT3: u8 = 0b100; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(u8)] +pub enum Sha2BaseFunct7 { + Sha256 = 0x1, + Sha512 = 0x2, +} /// The sha256 cryptographic hash function. #[inline(always)] @@ -13,6 +19,14 @@ pub fn sha256(input: &[u8]) -> [u8; 32] { output } +/// The sha512 cryptographic hash function. +#[inline(always)] +pub fn sha512(input: &[u8]) -> [u8; 64] { + let mut output = [0u8; 64]; + set_sha512(input, &mut output); + output +} + /// zkvm native implementation of sha256 /// # Safety /// @@ -26,7 +40,23 @@ pub fn sha256(input: &[u8]) -> [u8; 32] { #[inline(always)] #[no_mangle] extern "C" fn zkvm_sha256_impl(bytes: *const u8, len: usize, output: *mut u8) { - openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA256_FUNCT3, funct7 = SHA256_FUNCT7, rd = In output, rs1 = In bytes, rs2 = In len); + openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA2_FUNCT3, funct7 = Sha2BaseFunct7::Sha256 as u8, rd = In output, rs1 = In bytes, rs2 = In len); +} + +/// zkvm native implementation of sha512 +/// # Safety +/// +/// The VM accepts the preimage by pointer and length, and writes the +/// 64-byte hash. +/// - `bytes` must point to an input buffer at least `len` long. +/// - `output` must point to a buffer that is at least 64-bytes long. +/// +/// [`sha2-512`]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf +#[cfg(target_os = "zkvm")] +#[inline(always)] +#[no_mangle] +extern "C" fn zkvm_sha512_impl(bytes: *const u8, len: usize, output: *mut u8) { + openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA2_FUNCT3, funct7 = Sha2BaseFunct7::Sha512 as u8, rd = In output, rs1 = In bytes, rs2 = In len); } /// Sets `output` to the sha256 hash of `input`. @@ -43,3 +73,18 @@ pub fn set_sha256(input: &[u8], output: &mut [u8; 32]) { zkvm_sha256_impl(input.as_ptr(), input.len(), output.as_mut_ptr() as *mut u8); } } + +/// Sets `output` to the sha512 hash of `input`. +pub fn set_sha512(input: &[u8], output: &mut [u8; 64]) { + #[cfg(not(target_os = "zkvm"))] + { + use sha2::{Digest, Sha512}; + let mut hasher = Sha512::new(); + hasher.update(input); + output.copy_from_slice(hasher.finalize().as_ref()); + } + #[cfg(target_os = "zkvm")] + { + zkvm_sha512_impl(input.as_ptr(), input.len(), output.as_mut_ptr() as *mut u8); + } +} diff --git a/extensions/sha256/tests/programs/Cargo.toml b/extensions/sha256/tests/programs/Cargo.toml index dad3842cea..433ccdc311 100644 --- a/extensions/sha256/tests/programs/Cargo.toml +++ b/extensions/sha256/tests/programs/Cargo.toml @@ -1,6 +1,6 @@ [workspace] [package] -name = "openvm-keccak256-test-programs" +name = "openvm-sha256-test-programs" version = "0.0.0" edition = "2021" diff --git a/extensions/sha256/tests/programs/examples/sha.rs b/extensions/sha256/tests/programs/examples/sha.rs index fffbc677a7..45be16d5d6 100644 --- a/extensions/sha256/tests/programs/examples/sha.rs +++ b/extensions/sha256/tests/programs/examples/sha.rs @@ -7,24 +7,65 @@ use alloc::vec::Vec; use core::hint::black_box; use hex::FromHex; -use openvm_sha256_guest::sha256; +use openvm_sha256_guest::{sha256, sha512}; openvm::entry!(main); +struct ShaTestVector { + input: &'static str, + expected_output_sha256: &'static str, + expected_output_sha512: &'static str, +} + pub fn main() { let test_vectors = [ - ("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), - ("98c1c0bdb7d5fea9a88859f06c6c439f", "b6b2c9c9b6f30e5c66c977f1bd7ad97071bee739524aecf793384890619f2b05"), - ("5b58f4163e248467cc1cd3eecafe749e8e2baaf82c0f63af06df0526347d7a11327463c115210a46b6740244eddf370be89c", "ac0e25049870b91d78ef6807bb87fce4603c81abd3c097fba2403fd18b6ce0b7"), - ("9ad198539e3160194f38ac076a782bd5210a007560d1fce9ef78f8a4a5e4d78c6b96c250cff3520009036e9c6087d5dab587394edda862862013de49a12072485a6c01165ec0f28ffddf1873fbd53e47fcd02fb6a5ccc9622d5588a92429c663ce298cb71b50022fc2ec4ba9f5bbd250974e1a607b165fee16e8f3f2be20d7348b91a2f518ce928491900d56d9f86970611580350cee08daea7717fe28a73b8dcfdea22a65ed9f5a09198de38e4e4f2cc05b0ba3dd787a5363ab6c9f39dcb66c1a29209b1d6b1152769395df8150b4316658ea6ab19af94903d643fcb0ae4d598035ebe73c8b1b687df1ab16504f633c929569c6d0e5fae6eea43838fbc8ce2c2b43161d0addc8ccf945a9c4e06294e56a67df0000f561f61b630b1983ba403e775aaeefa8d339f669d1e09ead7eae979383eda983321e1743e5404b4b328da656de79ff52d179833a6bd5129f49432d74d001996c37c68d9ab49fcff8061d193576f396c20e1f0d9ee83a51290ba60efa9c3cb2e15b756321a7ca668cdbf63f95ec33b1c450aa100101be059dc00077245b25a6a66698dee81953ed4a606944076e2858b1420de0095a7f60b08194d6d9a997009d345c71f63a7034b976e409af8a9a040ac7113664609a7adedb76b2fadf04b0348392a1650526eb2a4d6ed5e4bbcda8aabc8488b38f4f5d9a398103536bb8250ed82a9b9825f7703c263f9e", "080ad71239852124fc26758982090611b9b19abf22d22db3a57f67a06e984a23") - + ShaTestVector { + input: "", + expected_output_sha256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + expected_output_sha512: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + }, + ShaTestVector { + input: "98c1c0bdb7d5fea9a88859f06c6c439f", + expected_output_sha256: "b6b2c9c9b6f30e5c66c977f1bd7ad97071bee739524aecf793384890619f2b05", + expected_output_sha512: "eb576959c531f116842c0cc915a29c8f71d7a285c894c349b83469002ef093d51f9f14ce4248488bff143025e47ed27c12badb9cd43779cb147408eea062d583", + }, + ShaTestVector { + input: "5b58f4163e248467cc1cd3eecafe749e8e2baaf82c0f63af06df0526347d7a11327463c115210a46b6740244eddf370be89c", + expected_output_sha256: "ac0e25049870b91d78ef6807bb87fce4603c81abd3c097fba2403fd18b6ce0b7", + expected_output_sha512: "a20d5fb14814d045a7d2861e80d2b688f1cd1daaba69e6bb1cc5233f514141ea4623b3373af702e78e3ec5dc8c1b716a37a9a2f5fbc9493b9df7043f5e99a8da", + }, + ShaTestVector { + input: "9ad198539e3160194f38ac076a782bd5210a007560d1fce9ef78f8a4a5e4d78c6b96c250cff3520009036e9c6087d5dab587394edda862862013de49a12072485a6c01165ec0f28ffddf1873fbd53e47fcd02fb6a5ccc9622d5588a92429c663ce298cb71b50022fc2ec4ba9f5bbd250974e1a607b165fee16e8f3f2be20d7348b91a2f518ce928491900d56d9f86970611580350cee08daea7717fe28a73b8dcfdea22a65ed9f5a09198de38e4e4f2cc05b0ba3dd787a5363ab6c9f39dcb66c1a29209b1d6b1152769395df8150b4316658ea6ab19af94903d643fcb0ae4d598035ebe73c8b1b687df1ab16504f633c929569c6d0e5fae6eea43838fbc8ce2c2b43161d0addc8ccf945a9c4e06294e56a67df0000f561f61b630b1983ba403e775aaeefa8d339f669d1e09ead7eae979383eda983321e1743e5404b4b328da656de79ff52d179833a6bd5129f49432d74d001996c37c68d9ab49fcff8061d193576f396c20e1f0d9ee83a51290ba60efa9c3cb2e15b756321a7ca668cdbf63f95ec33b1c450aa100101be059dc00077245b25a6a66698dee81953ed4a606944076e2858b1420de0095a7f60b08194d6d9a997009d345c71f63a7034b976e409af8a9a040ac7113664609a7adedb76b2fadf04b0348392a1650526eb2a4d6ed5e4bbcda8aabc8488b38f4f5d9a398103536bb8250ed82a9b9825f7703c263f9e", + expected_output_sha256: "080ad71239852124fc26758982090611b9b19abf22d22db3a57f67a06e984a23", + expected_output_sha512: "8d215ee6dc26757c210db0dd00c1c6ed16cc34dbd4bb0fa10c1edb6b62d5ab16aea88c881001b173d270676daf2d6381b5eab8711fa2f5589c477c1d4b84774f", + } ]; - for (input, expected_output) in test_vectors.iter() { + + for ( + i, + ShaTestVector { + input, + expected_output_sha256, + expected_output_sha512, + }, + ) in test_vectors.iter().enumerate() + { let input = Vec::from_hex(input).unwrap(); - let expected_output = Vec::from_hex(expected_output).unwrap(); - let output = sha256(&black_box(input)); - if output != *expected_output { - panic!(); + let expected_output_sha256 = Vec::from_hex(expected_output_sha256).unwrap(); + let output = sha256(black_box(&input)); + if output != *expected_output_sha256 { + panic!( + "sha256 test {i} failed on input: {:?}.\nexpected: {:?},\ngot: {:?}", + input, expected_output_sha256, output + ); + } + let expected_output_sha512 = Vec::from_hex(expected_output_sha512).unwrap(); + let output = sha512(black_box(&input)); + if output != *expected_output_sha512 { + panic!( + "sha512 test {i} failed on input: {:?}.\nexpected: {:?},\ngot: {:?}", + input, expected_output_sha512, output + ); } } } diff --git a/extensions/sha256/tests/src/lib.rs b/extensions/sha256/tests/src/lib.rs index 41ea37e8ae..77ecf1b952 100644 --- a/extensions/sha256/tests/src/lib.rs +++ b/extensions/sha256/tests/src/lib.rs @@ -6,8 +6,8 @@ mod tests { use openvm_rv32im_transpiler::{ Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension, }; - use openvm_sha256_circuit::Sha256Rv32Config; - use openvm_sha256_transpiler::Sha256TranspilerExtension; + use openvm_sha256_circuit::Sha2Rv32Config; + use openvm_sha256_transpiler::Sha2TranspilerExtension; use openvm_stark_sdk::p3_baby_bear::BabyBear; use openvm_toolchain_tests::{build_example_program_at_path, get_programs_dir}; use openvm_transpiler::{transpiler::Transpiler, FromElf}; @@ -23,9 +23,9 @@ mod tests { .with_extension(Rv32ITranspilerExtension) .with_extension(Rv32MTranspilerExtension) .with_extension(Rv32IoTranspilerExtension) - .with_extension(Sha256TranspilerExtension), + .with_extension(Sha2TranspilerExtension), )?; - air_test(Sha256Rv32Config::default(), openvm_exe); + air_test(Sha2Rv32Config::default(), openvm_exe); Ok(()) } } diff --git a/extensions/sha256/transpiler/src/lib.rs b/extensions/sha256/transpiler/src/lib.rs index 6b13efe055..a78ec612bf 100644 --- a/extensions/sha256/transpiler/src/lib.rs +++ b/extensions/sha256/transpiler/src/lib.rs @@ -1,6 +1,6 @@ use openvm_instructions::{riscv::RV32_MEMORY_AS, LocalOpcode}; use openvm_instructions_derive::LocalOpcode; -use openvm_sha256_guest::{OPCODE, SHA256_FUNCT3, SHA256_FUNCT7}; +use openvm_sha256_guest::{Sha2BaseFunct7, OPCODE, SHA2_FUNCT3}; use openvm_stark_backend::p3_field::PrimeField32; use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::RType; @@ -11,14 +11,15 @@ use strum::{EnumCount, EnumIter, FromRepr}; )] #[opcode_offset = 0x320] #[repr(usize)] -pub enum Rv32Sha256Opcode { +pub enum Rv32Sha2Opcode { SHA256, + SHA512, } #[derive(Default)] -pub struct Sha256TranspilerExtension; +pub struct Sha2TranspilerExtension; -impl TranspilerExtension for Sha256TranspilerExtension { +impl TranspilerExtension for Sha2TranspilerExtension { fn process_custom(&self, instruction_stream: &[u32]) -> Option> { if instruction_stream.is_empty() { return None; @@ -27,20 +28,29 @@ impl TranspilerExtension for Sha256TranspilerExtension { let opcode = (instruction_u32 & 0x7f) as u8; let funct3 = ((instruction_u32 >> 12) & 0b111) as u8; - if (opcode, funct3) != (OPCODE, SHA256_FUNCT3) { + if (opcode, funct3) != (OPCODE, SHA2_FUNCT3) { return None; } let dec_insn = RType::new(instruction_u32); - if dec_insn.funct7 != SHA256_FUNCT7 as u32 { - return None; + if dec_insn.funct7 == Sha2BaseFunct7::Sha256 as u32 { + let instruction = from_r_type( + Rv32Sha2Opcode::SHA256.global_opcode().as_usize(), + RV32_MEMORY_AS as usize, + &dec_insn, + true, + ); + Some(TranspilerOutput::one_to_one(instruction)) + } else if dec_insn.funct7 == Sha2BaseFunct7::Sha512 as u32 { + let instruction = from_r_type( + Rv32Sha2Opcode::SHA512.global_opcode().as_usize(), + RV32_MEMORY_AS as usize, + &dec_insn, + true, + ); + Some(TranspilerOutput::one_to_one(instruction)) + } else { + None } - let instruction = from_r_type( - Rv32Sha256Opcode::SHA256.global_opcode().as_usize(), - RV32_MEMORY_AS as usize, - &dec_insn, - true, - ); - Some(TranspilerOutput::one_to_one(instruction)) } } From cc43df82841ee8adcf527e620a6d3c0683c3a486 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 4 Apr 2025 16:00:05 -0400 Subject: [PATCH 12/27] Add SHA-384 support --- Cargo.lock | 7292 ----------------- crates/circuits/sha-air/src/config.rs | 66 + crates/circuits/sha-air/src/tests.rs | 15 +- crates/circuits/sha-air/src/trace.rs | 2 +- docs/specs/ISA.md | 3 +- docs/specs/RISCV.md | 1 + docs/specs/transpiler.md | 1 + extensions/sha256/circuit/src/extension.rs | 15 +- .../sha256/circuit/src/sha256_chip/air.rs | 26 +- .../sha256/circuit/src/sha256_chip/columns.rs | 3 - .../sha256/circuit/src/sha256_chip/config.rs | 30 +- .../sha256/circuit/src/sha256_chip/mod.rs | 67 +- .../sha256/circuit/src/sha256_chip/tests.rs | 38 +- .../sha256/circuit/src/sha256_chip/trace.rs | 2 +- extensions/sha256/guest/src/lib.rs | 44 + .../sha256/tests/programs/examples/sha.rs | 16 +- extensions/sha256/transpiler/src/lib.rs | 9 + 17 files changed, 275 insertions(+), 7355 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 2d9306f3c1..0000000000 --- a/Cargo.lock +++ /dev/null @@ -1,7292 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addchain" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" -dependencies = [ - "num-bigint 0.3.3", - "num-integer", - "num-traits", -] - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy 0.7.35", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "alloy-eip2930" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "serde", -] - -[[package]] -name = "alloy-eip7702" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c986539255fb839d1533c128e190e557e52ff652c9ef62939e233a81dd93f7e" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "derive_more 1.0.0", - "k256", - "serde", -] - -[[package]] -name = "alloy-primitives" -version = "0.8.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more 2.0.1", - "foldhash", - "hashbrown 0.15.2", - "indexmap 2.8.0", - "itoa", - "k256", - "keccak-asm", - "paste", - "proptest", - "rand", - "ruint", - "rustc-hash 2.1.1", - "serde", - "sha3", - "tiny-keccak", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" -dependencies = [ - "anstyle", - "once_cell", - "windows-sys 0.59.0", -] - -[[package]] -name = "anyhow" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint 0.4.6", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint 0.4.6", - "num-traits", - "paste", - "rustc_version 0.4.1", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint 0.4.6", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint 0.4.6", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint 0.4.6", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518bc5745a6264b5fd7b09dffb9667e400ee9e2bbe18555fac75e1fe9afa0df9" -dependencies = [ - "hex", - "num", -] - -[[package]] -name = "auto_impl" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "aws-config" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c39646d1a6b51240a1a23bb57ea4eebede7e16fbc237fdc876980233dcecb4f" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sdk-sso", - "aws-sdk-ssooidc", - "aws-sdk-sts", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "hex", - "http 1.3.1", - "ring", - "time", - "tokio", - "tracing", - "url", - "zeroize", -] - -[[package]] -name = "aws-credential-types" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4471bef4c22a06d2c7a1b6492493d3fdf24a805323109d6874f9c94d5906ac14" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aff45ffe35196e593ea3b9dd65b320e51e2dda95aff4390bc459e461d09c6ad" -dependencies = [ - "aws-credential-types", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "http-body 0.4.6", - "once_cell", - "percent-encoding", - "pin-project-lite", - "tracing", - "uuid", -] - -[[package]] -name = "aws-sdk-s3" -version = "1.80.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a36b09e8273d89c4f35ea122b83b30e48f906f3b644460d72a7d3656d1be93d" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-checksums", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "bytes", - "fastrand", - "hex", - "hmac", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "lru", - "once_cell", - "percent-encoding", - "regex-lite", - "sha2", - "tracing", - "url", -] - -[[package]] -name = "aws-sdk-sso" -version = "1.63.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1cb45b83b53b5cd55ee33fd9fd8a70750255a3f286e4dca20e882052f2b256f" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "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", - "tracing", -] - -[[package]] -name = "aws-sdk-ssooidc" -version = "1.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4d9bc075ea6238778ed3951b65d3cde8c3864282d64fdcd19f2a90c0609f1" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "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", - "tracing", -] - -[[package]] -name = "aws-sdk-sts" -version = "1.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819ccba087f403890fee4825eeab460e64c59345667d2b83a12cf544b581e3a7" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-query", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "fastrand", - "http 0.2.12", - "once_cell", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sigv4" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d03c3c05ff80d54ff860fe38c726f6f494c639ae975203a101335f223386db" -dependencies = [ - "aws-credential-types", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "crypto-bigint 0.5.5", - "form_urlencoded", - "hex", - "hmac", - "http 0.2.12", - "http 1.3.1", - "once_cell", - "p256 0.11.1", - "percent-encoding", - "ring", - "sha2", - "subtle", - "time", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-async" -version = "1.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "aws-smithy-checksums" -version = "0.63.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65d21e1ba6f2cdec92044f904356a19f5ad86961acf015741106cdfafd747c0" -dependencies = [ - "aws-smithy-http", - "aws-smithy-types", - "bytes", - "crc32c", - "crc32fast", - "crc64fast-nvme", - "hex", - "http 0.2.12", - "http-body 0.4.6", - "md-5", - "pin-project-lite", - "sha1", - "sha2", - "tracing", -] - -[[package]] -name = "aws-smithy-eventstream" -version = "0.60.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c45d3dddac16c5c59d553ece225a88870cf81b7b813c9cc17b78cf4685eac7a" -dependencies = [ - "aws-smithy-types", - "bytes", - "crc32fast", -] - -[[package]] -name = "aws-smithy-http" -version = "0.62.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -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", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http-client" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aff1159006441d02e57204bf57a1b890ba68bedb6904ffd2873c1c4c11c546b" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "h2 0.4.8", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper 1.6.0", - "hyper-rustls 0.24.2", - "hyper-rustls 0.27.5", - "hyper-util", - "pin-project-lite", - "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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" -dependencies = [ - "aws-smithy-types", - "urlencoding", -] - -[[package]] -name = "aws-smithy-runtime" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0152749e17ce4d1b47c7747bdfec09dac1ccafdcbc741ebf9daa2a373356730f" -dependencies = [ - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-http-client", - "aws-smithy-observability", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "fastrand", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "http-body 1.0.1", - "once_cell", - "pin-project-lite", - "pin-utils", - "tokio", - "tracing", -] - -[[package]] -name = "aws-smithy-runtime-api" -version = "1.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da37cf5d57011cb1753456518ec76e31691f1f474b73934a284eb2a1c76510f" -dependencies = [ - "aws-smithy-async", - "aws-smithy-types", - "bytes", - "http 0.2.12", - "http 1.3.1", - "pin-project-lite", - "tokio", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-types" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836155caafba616c0ff9b07944324785de2ab016141c3550bd1c07882f8cee8f" -dependencies = [ - "base64-simd", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "itoa", - "num-integer", - "pin-project-lite", - "pin-utils", - "ryu", - "serde", - "time", - "tokio", - "tokio-util", -] - -[[package]] -name = "aws-smithy-xml" -version = "0.60.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "aws-types" -version = "1.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3873f8deed8927ce8d04487630dc9ff73193bab64742a61d050e57a68dec4125" -dependencies = [ - "aws-credential-types", - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "rustc_version 0.4.1", - "tracing", -] - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "serde", - "windows-targets", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref", - "vsimd", -] - -[[package]] -name = "base64ct" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitcode" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf300f4aa6e66f3bdff11f1236a88c622fe47ea814524792240b4d554d9858ee" -dependencies = [ - "arrayvec", - "bitcode_derive", - "bytemuck", - "glam", - "serde", -] - -[[package]] -name = "bitcode_derive" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b6b4cb608b8282dc3b53d0f4c9ab404655d562674c682db7e6c0458cc83c23" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "blake2b_simd" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - -[[package]] -name = "blake3" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17679a8d69b6d7fd9cd9801a536cec9fa5e5970b69f9d4747f70b39b031f5e7" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bls12_381" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c196a77437e7cc2fb515ce413a6401291578b5afc8ecb29a3c7ab957f05941" -dependencies = [ - "ff 0.12.1", - "group 0.12.1", - "pairing 0.22.0", - "rand_core", - "subtle", -] - -[[package]] -name = "blst" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - -[[package]] -name = "bon" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65268237be94042665b92034f979c42d431d2fd998b49809543afe3e66abad1c" -dependencies = [ - "bon-macros", - "rustversion", -] - -[[package]] -name = "bon-macros" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "803c95b2ecf650eb10b5f87dda6b9f6a1b758cee53245e2b7b825c9b3803a443" -dependencies = [ - "darling", - "ident_case", - "prettyplease", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.100", -] - -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "byte-slice-cast" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" - -[[package]] -name = "bytemuck" -version = "1.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "bytes-utils" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" -dependencies = [ - "bytes", - "either", -] - -[[package]] -name = "c-kzg" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "once_cell", - "serde", -] - -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-openvm" -version = "1.0.0" -dependencies = [ - "aws-config", - "aws-sdk-s3", - "clap", - "eyre", - "hex", - "openvm-build", - "openvm-native-recursion", - "openvm-sdk", - "openvm-stark-backend", - "openvm-stark-sdk", - "openvm-transpiler", - "serde", - "serde_json", - "target-lexicon", - "tempfile", - "tokio", - "toml", - "tracing", - "vergen", -] - -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" -dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.26", - "serde", - "serde_json", - "thiserror 1.0.69", -] - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "windows-link", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "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.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "clap_lex" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "const-default" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" - -[[package]] -name = "const-hex" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const_format" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crc32c" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" -dependencies = [ - "rustc_version 0.4.1", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crc64fast-nvme" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4955638f00a809894c947f85a024020a20815b65a5eea633798ea7924edab2b3" -dependencies = [ - "crc", -] - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.100", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive-new" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "derive-new" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "derive_more" -version = "0.99.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.1", - "syn 2.0.100", -] - -[[package]] -name = "derive_more" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" -dependencies = [ - "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]] -name = "derive_more-impl" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "proc-macro2", - "quote", - "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", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "downcast-rs" -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.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der 0.7.9", - "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "elf" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core", - "sec1 0.3.0", - "subtle", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", - "digest 0.10.7", - "ff 0.13.1", - "generic-array", - "group 0.13.0", - "pkcs8 0.10.2", - "rand_core", - "sec1 0.7.3", - "subtle", - "zeroize", -] - -[[package]] -name = "embedded-alloc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" -dependencies = [ - "const-default", - "critical-section", - "linked_list_allocator", - "rlsf", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "enum_dispatch" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "enumn" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "env_filter" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" -dependencies = [ - "log", -] - -[[package]] -name = "env_logger" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "primitive-types", - "uint", -] - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "fastrlp" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "bitvec", - "rand_core", - "subtle", -] - -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "bitvec", - "byteorder", - "ff_derive", - "rand_core", - "subtle", -] - -[[package]] -name = "ff_derive" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f10d12652036b0e99197587c6ba87a8fc3031986499973c030d8b44fcc151b60" -dependencies = [ - "addchain", - "num-bigint 0.3.3", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "gcd" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "getset" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3586f256131df87204eb733da72e3d3eb4f343c639f4b7be279ac7c48baeafe" -dependencies = [ - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "git2" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" -dependencies = [ - "bitflags", - "libc", - "libgit2-sys", - "log", - "url", -] - -[[package]] -name = "glam" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3aa70d918d2b234126ff4f850f628f172542bf0603ded26b8ee36e5e22d5f9" - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "memuse", - "rand_core", - "subtle", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.1", - "rand_core", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "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", - "tracing", -] - -[[package]] -name = "half" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "halo2" -version = "0.1.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a23c779b38253fe1538102da44ad5bd5378495a61d2c4ee18d64eaa61ae5995" -dependencies = [ - "halo2_proofs", -] - -[[package]] -name = "halo2-axiom" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f0ca78d12ac5c893f286d7cdfe3869290305ab8cac376e2592cdc8396da102" -dependencies = [ - "blake2b_simd", - "crossbeam", - "ff 0.13.1", - "group 0.13.0", - "halo2curves-axiom", - "itertools 0.11.0", - "maybe-rayon", - "pairing 0.23.0", - "rand", - "rand_core", - "rayon", - "rustc-hash 1.1.0", - "sha3", - "tracing", -] - -[[package]] -name = "halo2-base" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678cf3adc0a39d7b4d9b82315a655201aa24a430dd1902b162c508047f56ac69" -dependencies = [ - "getset", - "halo2-axiom", - "itertools 0.11.0", - "log", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "poseidon-primitives", - "rand_chacha", - "rayon", - "rustc-hash 1.1.0", - "serde", - "serde_json", -] - -[[package]] -name = "halo2-ecc" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c00681fdd1febaf552d8814e9f5a6a142d81a1514102190da07039588b366" -dependencies = [ - "halo2-base", - "itertools 0.11.0", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "rand", - "rand_chacha", - "rand_core", - "rayon", - "serde", - "serde_json", - "test-case", -] - -[[package]] -name = "halo2_proofs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e925780549adee8364c7f2b685c753f6f3df23bde520c67416e93bf615933760" -dependencies = [ - "blake2b_simd", - "ff 0.12.1", - "group 0.12.1", - "pasta_curves 0.4.1", - "rand_core", - "rayon", -] - -[[package]] -name = "halo2curves" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b756596082144af6e57105a20403b7b80fe9dccd085700b74fae3af523b74dba" -dependencies = [ - "blake2", - "digest 0.10.7", - "ff 0.13.1", - "group 0.13.0", - "halo2derive", - "hex", - "lazy_static", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "pairing 0.23.0", - "paste", - "rand", - "rand_core", - "rayon", - "serde", - "serde_arrays", - "sha2", - "static_assertions", - "subtle", - "unroll", -] - -[[package]] -name = "halo2curves-axiom" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8309e4638b4f1bcf6613d72265a84074d26034c35edc5d605b5688e580b8b8" -dependencies = [ - "blake2b_simd", - "digest 0.10.7", - "ff 0.13.1", - "group 0.13.0", - "hex", - "lazy_static", - "num-bigint 0.4.6", - "num-traits", - "pairing 0.23.0", - "pasta_curves 0.5.1", - "paste", - "rand", - "rand_core", - "rayon", - "serde", - "serde_arrays", - "sha2", - "static_assertions", - "subtle", - "unroll", -] - -[[package]] -name = "halo2derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb99e7492b4f5ff469d238db464131b86c2eaac814a78715acba369f64d2c76" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.3.1", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http 1.3.1", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "tokio", - "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.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", - "serde", -] - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi 0.5.0", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -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.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "jubjub" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a575df5f985fe1cd5b2b05664ff6accfc46559032b954529fd225a2168d27b0f" -dependencies = [ - "bitvec", - "bls12_381", - "ff 0.12.1", - "group 0.12.1", - "rand_core", - "subtle", -] - -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "once_cell", - "sha2", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak-asm" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -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.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" - -[[package]] -name = "libgit2-sys" -version = "0.17.0+1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" -dependencies = [ - "cc", - "libc", - "libz-sys", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "libmimalloc-sys" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "libz-sys" -version = "1.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked_list_allocator" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" - -[[package]] -name = "linux-raw-sys" -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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "lockfree-object-pool" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.2", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memuse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" - -[[package]] -name = "metrics" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884adb57038347dfbaf2d5065887b6cf4312330dc8e94bc30a1a839bd79d3261" -dependencies = [ - "ahash", - "portable-atomic", -] - -[[package]] -name = "metrics-tracing-context" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62a6a1f7141f1d9bc7a886b87536bbfc97752e08b369e1e0453a9acfab5f5da4" -dependencies = [ - "indexmap 2.8.0", - "itoa", - "lockfree-object-pool", - "metrics", - "metrics-util", - "once_cell", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "metrics-util" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" -dependencies = [ - "aho-corasick", - "crossbeam-epoch", - "crossbeam-utils", - "hashbrown 0.14.5", - "indexmap 2.8.0", - "metrics", - "num_cpus", - "ordered-float", - "quanta", - "radix_trie", - "sketches-ddsketch", -] - -[[package]] -name = "mimalloc" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "ndarray" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "portable-atomic", - "portable-atomic-util", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint 0.4.6", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", - "rand", - "serde", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-format" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" -dependencies = [ - "arrayvec", - "itoa", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "nums" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3c74f925fb8cfc49a8022f2afce48a0683b70f9e439885594e84c5edbf5b01" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "rand", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b" - -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openvm" -version = "1.0.0" -dependencies = [ - "bytemuck", - "chrono", - "num-bigint 0.4.6", - "openvm-custom-insn", - "openvm-platform", - "openvm-rv32im-guest", - "serde", -] - -[[package]] -name = "openvm-algebra-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "halo2curves-axiom", - "itertools 0.14.0", - "num-bigint 0.4.6", - "num-traits", - "openvm-algebra-transpiler", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-mod-circuit-builder", - "openvm-pairing-guest", - "openvm-rv32-adapters", - "openvm-rv32im-circuit", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "serde-big-array", - "serde_with", - "strum", -] - -[[package]] -name = "openvm-algebra-complex-macros" -version = "0.1.0" -dependencies = [ - "openvm-macros-common", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-algebra-guest" -version = "1.0.0" -dependencies = [ - "halo2curves-axiom", - "num-bigint 0.4.6", - "openvm-algebra-complex-macros", - "openvm-algebra-moduli-macros", - "serde-big-array", - "strum_macros", -] - -[[package]] -name = "openvm-algebra-moduli-macros" -version = "1.0.0" -dependencies = [ - "openvm-macros-common", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-algebra-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "num-bigint 0.4.6", - "openvm-algebra-circuit", - "openvm-algebra-transpiler", - "openvm-circuit", - "openvm-ecc-circuit", - "openvm-instructions", - "openvm-rv32im-transpiler", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", -] - -[[package]] -name = "openvm-algebra-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-algebra-guest", - "openvm-instructions", - "openvm-instructions-derive", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "strum", -] - -[[package]] -name = "openvm-benchmarks" -version = "1.0.0" -dependencies = [ - "clap", - "criterion", - "derive-new 0.6.0", - "derive_more 1.0.0", - "eyre", - "k256", - "num-bigint 0.4.6", - "openvm-algebra-circuit", - "openvm-algebra-transpiler", - "openvm-build", - "openvm-circuit", - "openvm-ecc-circuit", - "openvm-ecc-transpiler", - "openvm-keccak256-circuit", - "openvm-keccak256-transpiler", - "openvm-native-circuit", - "openvm-native-compiler", - "openvm-native-recursion", - "openvm-pairing-circuit", - "openvm-pairing-guest", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", - "openvm-sdk", - "openvm-stark-backend", - "openvm-stark-sdk", - "openvm-transpiler", - "rand_chacha", - "serde", - "tempfile", - "tiny-keccak", - "tokio", - "tracing", -] - -[[package]] -name = "openvm-bigint-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "openvm-bigint-transpiler", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-rv32-adapters", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", -] - -[[package]] -name = "openvm-bigint-guest" -version = "1.0.0" -dependencies = [ - "num-bigint 0.4.6", - "num-traits", - "openvm", - "openvm-platform", - "serde", - "serde-big-array", - "strum_macros", -] - -[[package]] -name = "openvm-bigint-integration-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "openvm-bigint-circuit", - "openvm-bigint-transpiler", - "openvm-circuit", - "openvm-instructions", - "openvm-rv32im-transpiler", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", -] - -[[package]] -name = "openvm-bigint-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-bigint-guest", - "openvm-instructions", - "openvm-instructions-derive", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "strum", -] - -[[package]] -name = "openvm-build" -version = "1.0.0" -dependencies = [ - "cargo_metadata", - "eyre", - "openvm-platform", - "serde", - "serde_json", -] - -[[package]] -name = "openvm-circuit" -version = "1.0.0" -dependencies = [ - "backtrace", - "cfg-if", - "derivative", - "derive-new 0.6.0", - "derive_more 1.0.0", - "enum_dispatch", - "eyre", - "getset", - "itertools 0.14.0", - "metrics", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-native-circuit", - "openvm-native-compiler", - "openvm-poseidon2-air", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-baby-bear", - "rand", - "rustc-hash 2.1.1", - "serde", - "serde-big-array", - "static_assertions", - "test-log", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "openvm-circuit-derive" -version = "1.0.0" -dependencies = [ - "itertools 0.14.0", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-circuit-primitives" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "itertools 0.14.0", - "num-bigint 0.4.6", - "num-traits", - "openvm-circuit-primitives-derive", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "test-case", - "tracing", -] - -[[package]] -name = "openvm-circuit-primitives-derive" -version = "1.0.0" -dependencies = [ - "itertools 0.14.0", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-continuations" -version = "1.0.0" -dependencies = [ - "derivative", - "openvm-circuit", - "openvm-native-compiler", - "openvm-native-recursion", - "openvm-stark-backend", - "openvm-stark-sdk", - "serde", - "static_assertions", -] - -[[package]] -name = "openvm-custom-insn" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-ecc-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "eyre", - "lazy_static", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "once_cell", - "openvm-algebra-circuit", - "openvm-algebra-guest", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-ecc-guest", - "openvm-ecc-transpiler", - "openvm-instructions", - "openvm-mod-circuit-builder", - "openvm-rv32-adapters", - "openvm-rv32im-circuit", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "serde_with", - "strum", -] - -[[package]] -name = "openvm-ecc-guest" -version = "1.0.0" -dependencies = [ - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "group 0.13.0", - "halo2curves-axiom", - "hex-literal", - "k256", - "lazy_static", - "num-bigint 0.4.6", - "once_cell", - "openvm", - "openvm-algebra-guest", - "openvm-algebra-moduli-macros", - "openvm-custom-insn", - "openvm-ecc-sw-macros", - "openvm-rv32im-guest", - "p256 0.13.2", - "serde", - "strum_macros", -] - -[[package]] -name = "openvm-ecc-integration-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "hex-literal", - "num-bigint 0.4.6", - "openvm-algebra-circuit", - "openvm-algebra-transpiler", - "openvm-circuit", - "openvm-ecc-circuit", - "openvm-ecc-guest", - "openvm-ecc-transpiler", - "openvm-keccak256-transpiler", - "openvm-rv32im-transpiler", - "openvm-sdk", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", -] - -[[package]] -name = "openvm-ecc-sw-macros" -version = "1.0.0" -dependencies = [ - "openvm-macros-common", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-ecc-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-ecc-guest", - "openvm-instructions", - "openvm-instructions-derive", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "strum", -] - -[[package]] -name = "openvm-instructions" -version = "1.0.0" -dependencies = [ - "backtrace", - "derive-new 0.6.0", - "itertools 0.14.0", - "num-bigint 0.4.6", - "num-traits", - "openvm-instructions-derive", - "openvm-stark-backend", - "serde", - "strum", - "strum_macros", -] - -[[package]] -name = "openvm-instructions-derive" -version = "1.0.0" -dependencies = [ - "openvm-instructions", - "quote", - "strum", - "strum_macros", - "syn 2.0.100", -] - -[[package]] -name = "openvm-keccak256-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "hex", - "itertools 0.14.0", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-keccak256-transpiler", - "openvm-rv32im-circuit", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-keccak-air", - "rand", - "serde", - "serde-big-array", - "strum", - "tiny-keccak", - "tracing", -] - -[[package]] -name = "openvm-keccak256-guest" -version = "1.0.0" -dependencies = [ - "openvm-platform", - "tiny-keccak", -] - -[[package]] -name = "openvm-keccak256-integration-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "openvm-circuit", - "openvm-instructions", - "openvm-keccak256-circuit", - "openvm-keccak256-transpiler", - "openvm-rv32im-transpiler", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", -] - -[[package]] -name = "openvm-keccak256-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-instructions", - "openvm-instructions-derive", - "openvm-keccak256-guest", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "strum", -] - -[[package]] -name = "openvm-macros-common" -version = "1.0.0" -dependencies = [ - "syn 2.0.100", -] - -[[package]] -name = "openvm-mod-circuit-builder" -version = "1.0.0" -dependencies = [ - "halo2curves-axiom", - "itertools 0.14.0", - "num-bigint 0.4.6", - "num-traits", - "openvm-circuit", - "openvm-circuit-primitives", - "openvm-instructions", - "openvm-pairing-guest", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "serde_with", - "tracing", -] - -[[package]] -name = "openvm-native-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "eyre", - "itertools 0.14.0", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-native-compiler", - "openvm-poseidon2-air", - "openvm-rv32im-circuit", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "serde-big-array", - "static_assertions", - "strum", - "tracing", -] - -[[package]] -name = "openvm-native-compiler" -version = "1.0.0" -dependencies = [ - "backtrace", - "itertools 0.14.0", - "metrics", - "num-bigint 0.4.6", - "num-integer", - "openvm-circuit", - "openvm-instructions", - "openvm-instructions-derive", - "openvm-native-circuit", - "openvm-native-compiler-derive", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-symmetric", - "rand", - "serde", - "snark-verifier-sdk", - "strum", - "strum_macros", - "zkhash", -] - -[[package]] -name = "openvm-native-compiler-derive" -version = "1.0.0" -dependencies = [ - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openvm-native-recursion" -version = "1.0.0" -dependencies = [ - "bitcode", - "cfg-if", - "itertools 0.14.0", - "lazy_static", - "metrics", - "once_cell", - "openvm-circuit", - "openvm-native-circuit", - "openvm-native-compiler", - "openvm-native-compiler-derive", - "openvm-native-recursion", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-dft", - "p3-fri", - "p3-merkle-tree", - "p3-symmetric", - "rand", - "serde", - "serde_json", - "serde_with", - "snark-verifier-sdk", - "tempfile", - "tracing", -] - -[[package]] -name = "openvm-native-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-instructions", - "openvm-transpiler", - "p3-field", -] - -[[package]] -name = "openvm-pairing-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "eyre", - "halo2curves-axiom", - "itertools 0.14.0", - "num-bigint 0.4.6", - "num-traits", - "openvm-algebra-circuit", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-ecc-circuit", - "openvm-ecc-guest", - "openvm-instructions", - "openvm-mod-circuit-builder", - "openvm-pairing-guest", - "openvm-pairing-transpiler", - "openvm-rv32-adapters", - "openvm-rv32im-circuit", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "strum", -] - -[[package]] -name = "openvm-pairing-guest" -version = "1.0.0" -dependencies = [ - "group 0.13.0", - "halo2curves-axiom", - "hex-literal", - "itertools 0.14.0", - "lazy_static", - "num-bigint 0.4.6", - "num-traits", - "openvm", - "openvm-algebra-complex-macros", - "openvm-algebra-guest", - "openvm-algebra-moduli-macros", - "openvm-custom-insn", - "openvm-ecc-guest", - "openvm-ecc-sw-macros", - "openvm-platform", - "openvm-rv32im-guest", - "rand", - "serde", - "strum_macros", - "subtle", -] - -[[package]] -name = "openvm-pairing-integration-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "num-bigint 0.4.6", - "num-traits", - "openvm", - "openvm-algebra-circuit", - "openvm-algebra-transpiler", - "openvm-circuit", - "openvm-ecc-circuit", - "openvm-ecc-guest", - "openvm-ecc-transpiler", - "openvm-instructions", - "openvm-pairing-circuit", - "openvm-pairing-guest", - "openvm-pairing-transpiler", - "openvm-rv32im-transpiler", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", - "rand", -] - -[[package]] -name = "openvm-pairing-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-instructions", - "openvm-instructions-derive", - "openvm-pairing-guest", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "strum", -] - -[[package]] -name = "openvm-platform" -version = "1.0.0" -dependencies = [ - "critical-section", - "embedded-alloc", - "getrandom 0.2.15", - "libm", - "openvm-custom-insn", - "openvm-rv32im-guest", -] - -[[package]] -name = "openvm-poseidon2-air" -version = "1.0.0" -dependencies = [ - "derivative", - "lazy_static", - "openvm-stark-backend", - "openvm-stark-sdk", - "p3-monty-31", - "p3-poseidon2", - "p3-poseidon2-air", - "p3-symmetric", - "rand", - "zkhash", -] - -[[package]] -name = "openvm-prof" -version = "1.0.0" -dependencies = [ - "clap", - "eyre", - "itertools 0.14.0", - "num-format", - "serde", - "serde_json", -] - -[[package]] -name = "openvm-rv32-adapters" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "itertools 0.14.0", - "openvm-circuit", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-rv32im-circuit", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "serde-big-array", - "serde_with", -] - -[[package]] -name = "openvm-rv32im-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "eyre", - "num-bigint 0.4.6", - "num-integer", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "serde-big-array", - "strum", -] - -[[package]] -name = "openvm-rv32im-guest" -version = "1.0.0" -dependencies = [ - "openvm-custom-insn", - "strum_macros", -] - -[[package]] -name = "openvm-rv32im-integration-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "openvm", - "openvm-circuit", - "openvm-instructions", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", - "serde", - "test-case", -] - -[[package]] -name = "openvm-rv32im-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-instructions", - "openvm-instructions-derive", - "openvm-rv32im-guest", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "serde", - "strum", - "tracing", -] - -[[package]] -name = "openvm-sdk" -version = "1.0.0" -dependencies = [ - "async-trait", - "bitcode", - "bon", - "clap", - "derivative", - "derive_more 1.0.0", - "eyre", - "getset", - "itertools 0.14.0", - "metrics", - "openvm", - "openvm-algebra-circuit", - "openvm-algebra-transpiler", - "openvm-bigint-circuit", - "openvm-bigint-transpiler", - "openvm-build", - "openvm-circuit", - "openvm-continuations", - "openvm-ecc-circuit", - "openvm-ecc-transpiler", - "openvm-keccak256-circuit", - "openvm-keccak256-transpiler", - "openvm-native-circuit", - "openvm-native-compiler", - "openvm-native-recursion", - "openvm-pairing-circuit", - "openvm-pairing-transpiler", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", - "openvm-sha256-circuit", - "openvm-sha256-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "openvm-transpiler", - "p3-fri", - "serde", - "serde_json", - "serde_with", - "thiserror 1.0.69", - "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.98", -] - -[[package]] -name = "openvm-sha256-air" -version = "1.0.0" -dependencies = [ - "ndarray", - "openvm-circuit", - "openvm-circuit-primitives", - "openvm-sha-macros", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "sha2", -] - -[[package]] -name = "openvm-sha256-circuit" -version = "1.0.0" -dependencies = [ - "derive-new 0.6.0", - "derive_more 1.0.0", - "ndarray", - "openvm-circuit", - "openvm-circuit-derive", - "openvm-circuit-primitives", - "openvm-circuit-primitives-derive", - "openvm-instructions", - "openvm-rv32im-circuit", - "openvm-sha-air", - "openvm-sha-macros", - "openvm-sha256-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "rand", - "serde", - "sha2", - "strum", -] - -[[package]] -name = "openvm-sha256-guest" -version = "1.0.0" -dependencies = [ - "openvm-platform", - "sha2", -] - -[[package]] -name = "openvm-sha256-integration-tests" -version = "1.0.0" -dependencies = [ - "eyre", - "openvm-circuit", - "openvm-instructions", - "openvm-rv32im-transpiler", - "openvm-sha256-circuit", - "openvm-sha256-transpiler", - "openvm-stark-sdk", - "openvm-toolchain-tests", - "openvm-transpiler", -] - -[[package]] -name = "openvm-sha256-transpiler" -version = "1.0.0" -dependencies = [ - "openvm-instructions", - "openvm-instructions-derive", - "openvm-sha256-guest", - "openvm-stark-backend", - "openvm-transpiler", - "rrs-lib", - "strum", -] - -[[package]] -name = "openvm-stark-backend" -version = "1.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.0.0#884f8e6aabf72bde00dc51f1f1121277bff73b1e" -dependencies = [ - "bitcode", - "cfg-if", - "derivative", - "derive-new 0.7.0", - "itertools 0.14.0", - "metrics", - "mimalloc", - "p3-air", - "p3-challenger", - "p3-commit", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-uni-stark", - "p3-util", - "rayon", - "rustc-hash 2.1.1", - "serde", - "thiserror 1.0.69", - "tikv-jemallocator", - "tracing", -] - -[[package]] -name = "openvm-stark-sdk" -version = "1.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v1.0.0#884f8e6aabf72bde00dc51f1f1121277bff73b1e" -dependencies = [ - "derivative", - "derive_more 0.99.19", - "ff 0.13.1", - "itertools 0.14.0", - "metrics", - "metrics-tracing-context", - "metrics-util", - "openvm-stark-backend", - "p3-baby-bear", - "p3-blake3", - "p3-bn254-fr", - "p3-dft", - "p3-fri", - "p3-goldilocks", - "p3-keccak", - "p3-merkle-tree", - "p3-poseidon", - "p3-poseidon2", - "p3-symmetric", - "rand", - "serde", - "serde_json", - "static_assertions", - "toml", - "tracing", - "tracing-forest", - "tracing-subscriber", - "zkhash", -] - -[[package]] -name = "openvm-toolchain-tests" -version = "1.0.0" -dependencies = [ - "derive_more 1.0.0", - "eyre", - "num-bigint 0.4.6", - "openvm-algebra-circuit", - "openvm-algebra-transpiler", - "openvm-bigint-circuit", - "openvm-build", - "openvm-circuit", - "openvm-ecc-guest", - "openvm-instructions", - "openvm-platform", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", - "openvm-stark-backend", - "openvm-stark-sdk", - "openvm-transpiler", - "serde", - "tempfile", - "test-case", -] - -[[package]] -name = "openvm-transpiler" -version = "1.0.0" -dependencies = [ - "elf", - "eyre", - "openvm-instructions", - "openvm-platform", - "openvm-stark-backend", - "rrs-lib", - "thiserror 1.0.69", -] - -[[package]] -name = "ordered-float" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" -dependencies = [ - "num-traits", -] - -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "p256" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" -dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2", -] - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "elliptic-curve 0.13.8", -] - -[[package]] -name = "p3-air" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-field", - "p3-matrix", -] - -[[package]] -name = "p3-baby-bear" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-field", - "p3-mds", - "p3-monty-31", - "p3-poseidon2", - "p3-symmetric", - "rand", - "serde", -] - -[[package]] -name = "p3-blake3" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "blake3", - "p3-symmetric", - "p3-util", -] - -[[package]] -name = "p3-bn254-fr" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "ff 0.13.1", - "halo2curves", - "num-bigint 0.4.6", - "p3-field", - "p3-poseidon2", - "p3-symmetric", - "rand", - "serde", -] - -[[package]] -name = "p3-challenger" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-field", - "p3-maybe-rayon", - "p3-symmetric", - "p3-util", - "tracing", -] - -[[package]] -name = "p3-commit" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-challenger", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-util", - "serde", -] - -[[package]] -name = "p3-dft" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "tracing", -] - -[[package]] -name = "p3-field" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "nums", - "p3-maybe-rayon", - "p3-util", - "rand", - "serde", - "tracing", -] - -[[package]] -name = "p3-fri" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-challenger", - "p3-commit", - "p3-dft", - "p3-field", - "p3-interpolation", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "rand", - "serde", - "tracing", -] - -[[package]] -name = "p3-goldilocks" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "num-bigint 0.4.6", - "p3-dft", - "p3-field", - "p3-mds", - "p3-poseidon", - "p3-poseidon2", - "p3-symmetric", - "p3-util", - "rand", - "serde", -] - -[[package]] -name = "p3-interpolation" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", -] - -[[package]] -name = "p3-keccak" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-field", - "p3-symmetric", - "p3-util", - "tiny-keccak", -] - -[[package]] -name = "p3-keccak-air" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-air", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "rand", - "tracing", -] - -[[package]] -name = "p3-matrix" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-field", - "p3-maybe-rayon", - "p3-util", - "rand", - "serde", - "tracing", - "transpose", -] - -[[package]] -name = "p3-maybe-rayon" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "rayon", -] - -[[package]] -name = "p3-mds" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-symmetric", - "p3-util", - "rand", -] - -[[package]] -name = "p3-merkle-tree" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-commit", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-symmetric", - "p3-util", - "rand", - "serde", - "tracing", -] - -[[package]] -name = "p3-monty-31" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "num-bigint 0.4.6", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-mds", - "p3-poseidon2", - "p3-symmetric", - "p3-util", - "rand", - "serde", - "tracing", - "transpose", -] - -[[package]] -name = "p3-poseidon" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-field", - "p3-mds", - "p3-symmetric", - "rand", -] - -[[package]] -name = "p3-poseidon2" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "gcd", - "p3-field", - "p3-mds", - "p3-symmetric", - "rand", -] - -[[package]] -name = "p3-poseidon2-air" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "p3-air", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-poseidon2", - "p3-util", - "rand", - "tikv-jemallocator", - "tracing", -] - -[[package]] -name = "p3-symmetric" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-field", - "serde", -] - -[[package]] -name = "p3-uni-stark" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "itertools 0.14.0", - "p3-air", - "p3-challenger", - "p3-commit", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "serde", - "tracing", -] - -[[package]] -name = "p3-util" -version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c#1ba4e5c40417f4f7aae86bcca56b6484b4b2490b" -dependencies = [ - "serde", -] - -[[package]] -name = "pairing" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" -dependencies = [ - "group 0.12.1", -] - -[[package]] -name = "pairing" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" -dependencies = [ - "group 0.13.0", -] - -[[package]] -name = "parity-scale-codec" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fde3d0718baf5bc92f577d652001da0f8d54cd03a7974e118d04fc888dc23d" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "const_format", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "rustversion", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581c837bb6b9541ce7faa9377c20616e4fb7650f6b0f68bc93c827ee504fb7b3" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "pasta_curves" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc65faf8e7313b4b1fbaa9f7ca917a0eed499a9663be71477f87993604341d8" -dependencies = [ - "blake2b_simd", - "ff 0.12.1", - "group 0.12.1", - "lazy_static", - "rand", - "static_assertions", - "subtle", -] - -[[package]] -name = "pasta_curves" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" -dependencies = [ - "blake2b_simd", - "ff 0.13.1", - "group 0.13.0", - "lazy_static", - "rand", - "static_assertions", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" -dependencies = [ - "memchr", - "thiserror 2.0.12", - "ucd-trie", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.9", - "spki 0.7.3", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "portable-atomic" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4aaeda7a092e21165cc5f0cbc738e72a46f31c03c3cbd87b71ceae9d2d93bc" -dependencies = [ - "bitvec", - "ff 0.13.1", - "lazy_static", - "log", - "rand", - "rand_xorshift", - "thiserror 1.0.69", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy 0.8.24", -] - -[[package]] -name = "prettyplease" -version = "0.2.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" -dependencies = [ - "proc-macro2", - "syn 2.0.100", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "proc-macro2" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax 0.8.5", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quanta" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" -dependencies = [ - "crossbeam-utils", - "libc", - "once_cell", - "raw-cpuid", - "wasi 0.11.0+wasi-snapshot-preview1", - "web-sys", - "winapi", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "raw-cpuid" -version = "11.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-lite" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "revm" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15689a3c6a8d14b647b4666f2e236ef47b5a5133cdfd423f545947986fff7013" -dependencies = [ - "auto_impl", - "cfg-if", - "dyn-clone", - "revm-interpreter", - "revm-precompile", - "serde", - "serde_json", -] - -[[package]] -name = "revm-interpreter" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e3f11d0fed049a4a10f79820c59113a79b38aed4ebec786a79d5c667bfeb51" -dependencies = [ - "revm-primitives", - "serde", -] - -[[package]] -name = "revm-precompile" -version = "15.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e381060af24b750069a2b2d2c54bba273d84e8f5f9e8026fc9262298e26cc336" -dependencies = [ - "aurora-engine-modexp", - "blst", - "c-kzg", - "cfg-if", - "k256", - "once_cell", - "revm-primitives", - "ripemd", - "secp256k1", - "sha2", - "substrate-bn", -] - -[[package]] -name = "revm-primitives" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3702f132bb484f4f0d0ca4f6fbde3c82cfd745041abbedd6eda67730e1868ef0" -dependencies = [ - "alloy-eip2930", - "alloy-eip7702", - "alloy-primitives", - "auto_impl", - "bitflags", - "bitvec", - "c-kzg", - "cfg-if", - "dyn-clone", - "enumn", - "hex", - "serde", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac", - "zeroize", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rustc-hex", -] - -[[package]] -name = "rlsf" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf" -dependencies = [ - "cfg-if", - "const-default", - "libc", - "svgbobdoc", -] - -[[package]] -name = "rrs-lib" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4382d3af3a4ebdae7f64ba6edd9114fff92c89808004c4943b393377a25d001" -dependencies = [ - "downcast-rs", - "paste", -] - -[[package]] -name = "ruint" -version = "1.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ef8fb1dd8de3870cb8400d51b4c2023854bbafd5431a3ac7e7317243e22d2f" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp 0.3.1", - "fastrlp 0.4.0", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver 1.0.26", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "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", -] - -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "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]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "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.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.9", - "generic-array", - "pkcs8 0.10.2", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" -dependencies = [ - "rand", - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" -dependencies = [ - "cc", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "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", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" -dependencies = [ - "serde", -] - -[[package]] -name = "semver-parser" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-big-array" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_arrays" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38636132857f68ec3d5f3eb121166d2af33cb55174c4d5ff645db6165cbef0fd" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "indexmap 2.8.0", - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.8.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "sha3-asm" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" -dependencies = [ - "cc", - "cfg-if", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "sketches-ddsketch" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" - -[[package]] -name = "snark-verifier" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e4c4ed1edca41687fe2d8a09ba30badb0a5cc7fa56dd1159d62aeab7c99ace" -dependencies = [ - "halo2-base", - "halo2-ecc", - "hex", - "itertools 0.11.0", - "lazy_static", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "pairing 0.23.0", - "rand", - "revm", - "ruint", - "serde", - "sha3", -] - -[[package]] -name = "snark-verifier-sdk" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babff70ce6292fce03f692d68569f76b8f6710dbac7be7fe5f32c915909c9065" -dependencies = [ - "bincode", - "ethereum-types", - "getset", - "halo2-base", - "hex", - "itertools 0.11.0", - "lazy_static", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "rand", - "rand_chacha", - "serde", - "serde_json", - "snark-verifier", -] - -[[package]] -name = "socket2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der 0.7.9", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strength_reduce" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.100", -] - -[[package]] -name = "substrate-bn" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" -dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand", - "rustc-hex", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "svgbobdoc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" -dependencies = [ - "base64 0.13.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-width", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] -name = "tempfile" -version = "3.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" -dependencies = [ - "fastrand", - "getrandom 0.3.2", - "once_cell", - "rustix 1.0.3", - "windows-sys 0.59.0", -] - -[[package]] -name = "test-case" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" -dependencies = [ - "test-case-macros", -] - -[[package]] -name = "test-case-core" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "test-case-macros" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "test-case-core", -] - -[[package]] -name = "test-log" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f" -dependencies = [ - "env_logger", - "test-log-macros", - "tracing-subscriber", -] - -[[package]] -name = "test-log-macros" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tikv-jemalloc-sys" -version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" -dependencies = [ - "libc", - "tikv-jemalloc-sys", -] - -[[package]] -name = "time" -version = "0.3.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" -dependencies = [ - "deranged", - "itoa", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" - -[[package]] -name = "time-macros" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tokio" -version = "1.44.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "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.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" -dependencies = [ - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-forest" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" -dependencies = [ - "ansi_term", - "smallvec", - "thiserror 1.0.69", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "transpose" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" -dependencies = [ - "num-integer", - "strength_reduce", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "unroll" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vergen" -version = "8.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" -dependencies = [ - "anyhow", - "cfg-if", - "git2", - "rustversion", - "time", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - -[[package]] -name = "wait-timeout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" -dependencies = [ - "libc", -] - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "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]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zkhash" -version = "0.2.0" -source = "git+https://github.com/HorizenLabs/poseidon2.git?rev=bb476b9#bb476b9ca38198cf5092487283c8b8c5d4317c4e" -dependencies = [ - "ark-ff 0.4.2", - "ark-std 0.4.0", - "bitvec", - "blake2", - "bls12_381", - "byteorder", - "cfg-if", - "group 0.12.1", - "group 0.13.0", - "halo2", - "hex", - "jubjub", - "lazy_static", - "pasta_curves 0.5.1", - "rand", - "serde", - "sha2", - "sha3", - "subtle", -] diff --git a/crates/circuits/sha-air/src/config.rs b/crates/circuits/sha-air/src/config.rs index 986ca1480b..3fdbb24f40 100644 --- a/crates/circuits/sha-air/src/config.rs +++ b/crates/circuits/sha-air/src/config.rs @@ -279,6 +279,72 @@ pub const SHA512_H: [u64; 8] = [ 0x5be0cd19137e2179, ]; +#[derive(Clone)] +pub struct Sha384Config; + +impl ShaConfig for Sha384Config { + // ==== Do not change these constants! ==== + type Word = u64; + /// Number of bits in a SHA384 word + const WORD_BITS: usize = 64; + /// Number of words in a SHA384 block + const BLOCK_WORDS: usize = 16; + /// Number of rows per block + const ROWS_PER_BLOCK: usize = 21; + /// 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 SHA384 hash + const HASH_WORDS: usize = 8; + /// Number of vars needed to encode the row index with [Encoder] + const ROW_VAR_CNT: usize = 6; + + fn get_invalid_carry_a(round_num: usize) -> &'static [u32] { + &SHA384_INVALID_CARRY_A[round_num] + } + fn get_invalid_carry_e(round_num: usize) -> &'static [u32] { + &SHA384_INVALID_CARRY_E[round_num] + } + fn get_k() -> &'static [u64] { + &SHA384_K + } + fn get_h() -> &'static [u64] { + &SHA384_H + } +} + +pub(crate) const SHA384_INVALID_CARRY_A: [[u32; Sha384Config::WORD_U16S]; + Sha384Config::ROUNDS_PER_ROW] = [ + [1571481603, 1428841901, 1050676523, 793575075], + [1233315842, 1822329223, 112923808, 1874228927], + [1245603842, 927240770, 1579759431, 70557227], + [195532801, 594312107, 1429379950, 220407092], +]; + +pub(crate) const SHA384_INVALID_CARRY_E: [[u32; Sha384Config::WORD_U16S]; + Sha384Config::ROUNDS_PER_ROW] = [ + [1067980802, 1508061099, 1418826213, 1232569491], + [1453086722, 1702524575, 152427899, 238512408], + [1623674882, 701393097, 1002035664, 4776891], + [1888911362, 184963225, 1151849224, 1034237098], +]; + +/// SHA384 constant K's +pub const SHA384_K: [u64; 80] = SHA512_K; + +/// SHA384 initial hash values +pub const SHA384_H: [u64; 8] = [ + 0xcbbb9d5dc1059ed8, + 0x629a292a367cd507, + 0x9159015a3070dd17, + 0x152fecd8f70e5939, + 0x67332667ffc00b31, + 0x8eb44a8768581511, + 0xdb0c2e0d64f98fa7, + 0x47b5481dbefa4fa4, +]; + // Needed to avoid compile errors in utils.rs // not sure why this doesn't inf loop pub trait RotateRight { diff --git a/crates/circuits/sha-air/src/tests.rs b/crates/circuits/sha-air/src/tests.rs index 479748f5ff..cf40d411d8 100644 --- a/crates/circuits/sha-air/src/tests.rs +++ b/crates/circuits/sha-air/src/tests.rs @@ -1,4 +1,4 @@ -use crate::{ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut}; +use crate::{Sha384Config, ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut}; use std::{borrow::BorrowMut, cmp::max, sync::Arc}; use openvm_circuit::arch::{ @@ -22,7 +22,7 @@ use openvm_stark_backend::{ use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; -use crate::{compose, small_sig0_field, Sha256Config, Sha512Config, Sha2Air, ShaConfig}; +use crate::{compose, small_sig0_field, Sha256Config, Sha2Air, Sha512Config, ShaConfig}; // A wrapper AIR purely for testing purposes #[derive(Clone, Debug)] @@ -121,6 +121,11 @@ fn rand_sha512_test() { rand_sha_test::(); } +#[test] +fn rand_sha384_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 { @@ -282,3 +287,9 @@ fn test_sha256_final_hash_constraints() { fn test_sha512_final_hash_constraints() { test_sha_final_hash_constraints::(); } + +#[test] +#[should_panic] +fn test_sha384_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 f462864029..e21795179c 100644 --- a/crates/circuits/sha-air/src/trace.rs +++ b/crates/circuits/sha-air/src/trace.rs @@ -563,7 +563,7 @@ impl Sha2Air { /// 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 + /// Puts the correct carries in the `next_row`, the resulting carries can be out of bounds pub fn generate_carry_ae( local_cols: ShaRoundColsRef, next_cols: &mut ShaRoundColsRefMut, diff --git a/docs/specs/ISA.md b/docs/specs/ISA.md index 7cdb69c0f7..959059c89e 100644 --- a/docs/specs/ISA.md +++ b/docs/specs/ISA.md @@ -546,7 +546,8 @@ meaning all memory cells are constrained to be bytes. | Name | Operands | Description | | ----------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | SHA256_RV32 | `a,b,c,1,2` | `[r32{0}(a):32]_2 = sha256([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Does the necessary padding. Performs memory reads with block size `16` and writes with block size `32`. | -| SHA512_RV32 | `a,b,c,1,2` | `[r32{0}(a):64]_2 = sha512([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Does the necessary padding. Performs memory reads with block size `16` and writes with block size `64`. | +| SHA512_RV32 | `a,b,c,1,2` | `[r32{0}(a):64]_2 = sha512([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Does the necessary padding. Performs memory reads with block size `16` and writes with block size `32`. | +| SHA384_RV32 | `a,b,c,1,2` | `[r32{0}(a):64]_2 = sha384([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Does the necessary padding. Performs memory reads with block size `16` and writes with block size `32`. Writes 64 bytes to memory: the first 48 are the SHA-384 digest and the last 16 are zeros. | ### BigInt Extension diff --git a/docs/specs/RISCV.md b/docs/specs/RISCV.md index 113ba0d731..6b79d3d962 100644 --- a/docs/specs/RISCV.md +++ b/docs/specs/RISCV.md @@ -84,6 +84,7 @@ the guest must take care to validate all data and account for behavior in cases | ----------- | --- | ----------- | ------ | ------ | ---------------------------------------- | | sha256 | R | 0001011 | 100 | 0x1 | `[rd:32]_2 = sha256([rs1..rs1 + rs2]_2)` | | sha512 | R | 0001011 | 100 | 0x2 | `[rd:32]_2 = sha512([rs1..rs1 + rs2]_2)` | +| sha384 | R | 0001011 | 100 | 0x3 | `[rd:32]_2 = sha384([rs1..rs1 + rs2]_2)` | ## BigInt Extension diff --git a/docs/specs/transpiler.md b/docs/specs/transpiler.md index 1e5da4be4b..8afa9c3d7f 100644 --- a/docs/specs/transpiler.md +++ b/docs/specs/transpiler.md @@ -157,6 +157,7 @@ Each VM extension's behavior is specified below. | ----------- | ----------------------------------------------- | | sha256 | SHA256_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | | sha512 | SHA512_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | +| sha384 | SHA384_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | ### BigInt Extension diff --git a/extensions/sha256/circuit/src/extension.rs b/extensions/sha256/circuit/src/extension.rs index abd40002e2..f95b3215eb 100644 --- a/extensions/sha256/circuit/src/extension.rs +++ b/extensions/sha256/circuit/src/extension.rs @@ -14,7 +14,7 @@ use openvm_rv32im_circuit::{ Rv32MExecutor, Rv32MPeriphery, }; use openvm_sha256_transpiler::Rv32Sha2Opcode; -use openvm_sha_air::{Sha256Config, Sha512Config}; +use openvm_sha_air::{Sha256Config, Sha384Config, Sha512Config}; use openvm_stark_backend::p3_field::PrimeField32; use serde::{Deserialize, Serialize}; @@ -53,6 +53,7 @@ pub struct Sha2; pub enum Sha2Executor { Sha256(Sha2VmChip), Sha512(Sha2VmChip), + Sha384(Sha2VmChip), } #[derive(From, ChipUsageGetter, Chip, AnyEnum)] @@ -95,13 +96,23 @@ impl VmExtension for Sha2 { let sha512_chip = Sha2VmChip::::new( builder.system_port(), builder.system_config().memory_config.pointer_max_bits, - bitwise_lu_chip, + bitwise_lu_chip.clone(), builder.new_bus_idx(), Rv32Sha2Opcode::CLASS_OFFSET, builder.system_base().offline_memory(), ); inventory.add_executor(sha512_chip, vec![Rv32Sha2Opcode::SHA512.global_opcode()])?; + let sha384_chip = Sha2VmChip::::new( + builder.system_port(), + builder.system_config().memory_config.pointer_max_bits, + bitwise_lu_chip, + builder.new_bus_idx(), + Rv32Sha2Opcode::CLASS_OFFSET, + builder.system_base().offline_memory(), + ); + inventory.add_executor(sha384_chip, vec![Rv32Sha2Opcode::SHA384.global_opcode()])?; + Ok(inventory) } } diff --git a/extensions/sha256/circuit/src/sha256_chip/air.rs b/extensions/sha256/circuit/src/sha256_chip/air.rs index ddd7528eb3..e6c9a6863c 100644 --- a/extensions/sha256/circuit/src/sha256_chip/air.rs +++ b/extensions/sha256/circuit/src/sha256_chip/air.rs @@ -1,4 +1,5 @@ use std::cmp::min; +use std::convert::TryInto; use openvm_circuit::{ arch::ExecutionBridge, @@ -457,7 +458,7 @@ impl Sha2VmAir { .when(not::(is_last_row.clone())) .assert_eq(*next_cols.control.len, *local_cols.control.len); - // Read ptr should increment by [SHA256_READ_SIZE] for the first 4 rows and stay the same otherwise + // Read ptr should increment by [C::READ_SIZE] for the first 4 rows and stay the same otherwise let read_ptr_delta = *local_cols.inner.flags.is_first_4_rows * AB::Expr::from_canonical_usize(C::READ_SIZE); builder @@ -510,7 +511,8 @@ impl Sha2VmAir { ) .eval(builder, *local_cols.inner.flags.is_first_4_rows); } - Sha2Variant::Sha512 => { + // Sha512 and Sha384 have the same read size so we put them together + Sha2Variant::Sha512 | Sha2Variant::Sha384 => { let message: [AB::Var; Sha512Config::READ_SIZE] = message.try_into().unwrap_or_else(|_| { panic!("message is not the correct size"); @@ -610,10 +612,10 @@ impl Sha2VmAir { // the number of reads that happened to read the entire message: we do 4 reads per block let time_delta = (*local_cols.inner.flags.local_block_idx + AB::Expr::ONE) * AB::Expr::from_canonical_usize(4); - // Every time we read the message we increment the read pointer by SHA256_READ_SIZE + // Every time we read the message we increment the read pointer by C::READ_SIZE let read_ptr_delta = time_delta.clone() * AB::Expr::from_canonical_usize(C::READ_SIZE); - let result: Vec = (0..C::DIGEST_SIZE) + let result: Vec = (0..C::HASH_SIZE) .map(|i| { // The limbs are written in big endian order to the memory so need to be reversed local_cols.inner.final_hash[[i / C::WORD_U8S, C::WORD_U8S - i % C::WORD_U8S - 1]] @@ -630,7 +632,7 @@ impl Sha2VmAir { debug_assert_eq!(C::NUM_WRITES, 1); debug_assert_eq!(local_cols.writes_aux_base.len(), 1); debug_assert_eq!(local_cols.writes_aux_prev_data.nrows(), 1); - let prev_data: [AB::Var; Sha256Config::DIGEST_SIZE] = local_cols + let prev_data: [AB::Var; Sha256Config::HASH_SIZE] = local_cols .writes_aux_prev_data .row(0) .to_vec() @@ -654,13 +656,20 @@ impl Sha2VmAir { ) .eval(builder, is_last_row.clone()); } - Sha2Variant::Sha512 => { + Sha2Variant::Sha512 | Sha2Variant::Sha384 => { debug_assert_eq!(C::NUM_WRITES, 2); debug_assert_eq!(local_cols.writes_aux_base.len(), 2); debug_assert_eq!(local_cols.writes_aux_prev_data.nrows(), 2); + + // For Sha384, set the last 16 cells to 0 + let mut truncated_result: Vec = + result.iter().map(|x| (*x).into()).collect(); + for x in truncated_result.iter_mut().skip(C::DIGEST_SIZE) { + *x = AB::Expr::ZERO; + } + // write the digest in two halves because we only support writes up to 32 bytes for i in 0..Sha512Config::NUM_WRITES { - // for i in 0..1 { let prev_data: [AB::Var; Sha512Config::WRITE_SIZE] = local_cols .writes_aux_prev_data .row(i) @@ -677,8 +686,9 @@ impl Sha2VmAir { dst_ptr_val.clone() + AB::Expr::from_canonical_usize(i * Sha512Config::WRITE_SIZE), ), - result + truncated_result [i * Sha512Config::WRITE_SIZE..(i + 1) * Sha512Config::WRITE_SIZE] + .to_vec() .try_into() .unwrap_or_else(|_| { panic!("result is not the correct size"); diff --git a/extensions/sha256/circuit/src/sha256_chip/columns.rs b/extensions/sha256/circuit/src/sha256_chip/columns.rs index 447da18b94..ecd56b63db 100644 --- a/extensions/sha256/circuit/src/sha256_chip/columns.rs +++ b/extensions/sha256/circuit/src/sha256_chip/columns.rs @@ -53,7 +53,6 @@ pub struct ShaVmDigestCols< const ROUNDS_PER_ROW: usize, const ROUNDS_PER_ROW_MINUS_ONE: usize, const ROW_VAR_CNT: usize, - const DIGEST_SIZE: usize, const NUM_WRITES: usize, const WRITE_SIZE: usize, > { @@ -85,8 +84,6 @@ pub struct ShaVmDigestCols< pub writes_aux_prev_data: [[T; WRITE_SIZE]; NUM_WRITES], } -pub type Sha256VmDigestCols = ShaVmDigestCols; - /// These are the columns that are used on both round and digest rows #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] diff --git a/extensions/sha256/circuit/src/sha256_chip/config.rs b/extensions/sha256/circuit/src/sha256_chip/config.rs index 7989e916b5..bddb29a5f3 100644 --- a/extensions/sha256/circuit/src/sha256_chip/config.rs +++ b/extensions/sha256/circuit/src/sha256_chip/config.rs @@ -1,12 +1,13 @@ use openvm_instructions::riscv::RV32_CELL_BITS; use openvm_sha256_transpiler::Rv32Sha2Opcode; -use openvm_sha_air::{Sha256Config, Sha512Config, ShaConfig}; +use openvm_sha_air::{Sha256Config, Sha384Config, Sha512Config, ShaConfig}; use super::{ShaVmControlColsRef, ShaVmDigestColsRef, ShaVmRoundColsRef}; pub enum Sha2Variant { Sha256, Sha512, + Sha384, } pub trait ShaChipConfig: ShaConfig { @@ -44,13 +45,15 @@ pub trait ShaChipConfig: ShaConfig { /// Number of cells to read in a single memory access const READ_SIZE: usize = Self::WORD_U8S * Self::ROUNDS_PER_ROW; - /// Number of cells in the digest - const DIGEST_SIZE: usize = Self::WORD_U8S * Self::HASH_WORDS; - /// Digest will be written in NUM_WRITES parts of equal size - /// NUM_WRITES must divide DIGEST_SIZE + /// Number of cells in the digest before truncation (Sha384 truncates the digest) + const HASH_SIZE: usize = Self::WORD_U8S * Self::HASH_WORDS; + /// Number of cells in the digest after truncation + const DIGEST_SIZE: usize; + + /// Number of parts to write the hash in. Must divide HASH_SIZE const NUM_WRITES: usize; /// Size of each write - const WRITE_SIZE: usize = Self::DIGEST_SIZE / Self::NUM_WRITES; + const WRITE_SIZE: usize = Self::HASH_SIZE / Self::NUM_WRITES; } /// Register reads to get dst, src, len @@ -62,6 +65,8 @@ impl ShaChipConfig for Sha256Config { const MESSAGE_LENGTH_BITS: usize = 64; const NUM_WRITES: usize = 1; const OPCODE: Rv32Sha2Opcode = Rv32Sha2Opcode::SHA256; + // no truncation + const DIGEST_SIZE: usize = Self::HASH_SIZE; } // Currently same as Sha256Config, but can configure later @@ -72,4 +77,17 @@ impl ShaChipConfig for Sha512Config { // Use 2 writes because we only support writes up to 32 bytes const NUM_WRITES: usize = 2; const OPCODE: Rv32Sha2Opcode = Rv32Sha2Opcode::SHA512; + // no truncation + const DIGEST_SIZE: usize = Self::HASH_SIZE; +} + +impl ShaChipConfig for Sha384Config { + const VARIANT: Sha2Variant = Sha2Variant::Sha384; + const OPCODE_NAME: &'static str = "SHA384"; + const MESSAGE_LENGTH_BITS: usize = 128; + // Use 2 writes because we only support writes up to 32 bytes + const NUM_WRITES: usize = 2; + const OPCODE: Rv32Sha2Opcode = Rv32Sha2Opcode::SHA384; + // Sha284 truncates the output to 48 cells + const DIGEST_SIZE: usize = 48; } diff --git a/extensions/sha256/circuit/src/sha256_chip/mod.rs b/extensions/sha256/circuit/src/sha256_chip/mod.rs index 37a82e7725..61e8d14293 100644 --- a/extensions/sha256/circuit/src/sha256_chip/mod.rs +++ b/extensions/sha256/circuit/src/sha256_chip/mod.rs @@ -15,14 +15,12 @@ use openvm_instructions::{ instruction::Instruction, program::DEFAULT_PC_STEP, riscv::{RV32_MEMORY_AS, RV32_REGISTER_AS}, - LocalOpcode, }; use openvm_rv32im_circuit::adapters::read_rv32_register; -use openvm_sha256_transpiler::Rv32Sha2Opcode; use openvm_sha_air::{Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{interaction::BusIndex, p3_field::PrimeField32}; use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256, Sha512}; +use sha2::{Digest, Sha256, Sha384, Sha512}; mod air; mod columns; @@ -43,7 +41,6 @@ pub struct Sha2VmChip { pub records: Vec>, pub offline_memory: Arc>>, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - offset: usize, } @@ -95,20 +92,7 @@ impl InstructionExecutor for Sha2VmChip, from_state: ExecutionState, ) -> Result, ExecutionError> { - let &Instruction { - opcode, - a, - b, - c, - d, - e, - .. - } = instruction; - let local_opcode = opcode.local_opcode_idx(self.offset); - debug_assert!( - local_opcode == Rv32Sha2Opcode::SHA256.local_usize() - || local_opcode == Rv32Sha2Opcode::SHA512.local_usize() - ); + let &Instruction { a, b, c, d, e, .. } = instruction; debug_assert_eq!(d, F::from_canonical_u32(RV32_REGISTER_AS)); debug_assert_eq!(e, F::from_canonical_u32(RV32_MEMORY_AS)); @@ -131,18 +115,20 @@ impl InstructionExecutor for Sha2VmChip(hasher, num_blocks, src, len, dst, memory, e); - } else if C::OPCODE_NAME == "SHA512" { - let hasher = Sha512::new(); - hash_result = - execute_hash::(hasher, num_blocks, src, len, dst, memory, e); - } else { - panic!("Unsupported opcode: {}", C::OPCODE_NAME); - } + let hash_result: HashResult = match C::VARIANT { + Sha2Variant::Sha256 => { + let hasher = Sha256::new(); + execute_hash::(hasher, num_blocks, src, len, dst, memory, e) + } + Sha2Variant::Sha512 => { + let hasher = Sha512::new(); + execute_hash::(hasher, num_blocks, src, len, dst, memory, e) + } + Sha2Variant::Sha384 => { + let hasher = Sha384::new(); + execute_hash::(hasher, num_blocks, src, len, dst, memory, e) + } + }; self.records.push(Sha2Record { from_state: from_state.map(F::from_canonical_u32), @@ -184,21 +170,20 @@ fn execute_hash( let mut read_ptr = src; for _ in 0..num_blocks { let block_reads_records = (0..C::NUM_READ_ROWS) - .map(|i| { - if C::OPCODE_NAME == "SHA256" { + .map(|i| match C::VARIANT { + Sha2Variant::Sha256 => { let (id, data) = memory.read::<{ Sha256Config::READ_SIZE }>( address_space, F::from_canonical_u32(read_ptr + (i * C::READ_SIZE) as u32), ); (id, data.to_vec()) - } else if C::OPCODE_NAME == "SHA512" { + } + Sha2Variant::Sha512 | Sha2Variant::Sha384 => { let (id, data) = memory.read::<{ Sha512Config::READ_SIZE }>( address_space, F::from_canonical_u32(read_ptr + (i * C::READ_SIZE) as u32), ); (id, data.to_vec()) - } else { - panic!("unsupported opcode: {}", C::OPCODE_NAME); } }) .collect::>(); @@ -222,6 +207,8 @@ fn execute_hash( let mut digest = vec![0u8; C::DIGEST_SIZE]; digest.copy_from_slice(hasher.finalize().as_ref()); + // Pad with zeros + digest.resize(C::HASH_SIZE, 0); match C::VARIANT { Sha2Variant::Sha256 => { @@ -242,7 +229,7 @@ fn execute_hash( digest_writes: vec![digest_write], } } - Sha2Variant::Sha512 => { + Sha2Variant::Sha512 | Sha2Variant::Sha384 => { debug_assert_eq!(C::NUM_WRITES, 2); // write the digest in two halves because we only support writes up to 32 bytes let digest = digest @@ -269,7 +256,6 @@ fn execute_hash( } } -// Returns a Vec of length C::DIGEST_SIZE pub fn sha2_solve(input_message: &[u8]) -> Vec { match C::VARIANT { Sha2Variant::Sha256 => { @@ -286,5 +272,12 @@ pub fn sha2_solve(input_message: &[u8]) -> Vec { output.copy_from_slice(hasher.finalize().as_ref()); output } + Sha2Variant::Sha384 => { + let mut hasher = Sha384::new(); + hasher.update(input_message); + let mut output = vec![0u8; C::DIGEST_SIZE]; + output.copy_from_slice(hasher.finalize().as_ref()); + output + } } } diff --git a/extensions/sha256/circuit/src/sha256_chip/tests.rs b/extensions/sha256/circuit/src/sha256_chip/tests.rs index 99181579b1..09ef237b33 100644 --- a/extensions/sha256/circuit/src/sha256_chip/tests.rs +++ b/extensions/sha256/circuit/src/sha256_chip/tests.rs @@ -7,7 +7,7 @@ use openvm_circuit_primitives::bitwise_op_lookup::{ }; use openvm_instructions::{instruction::Instruction, riscv::RV32_CELL_BITS, LocalOpcode}; use openvm_sha256_transpiler::Rv32Sha2Opcode::{self, *}; -use openvm_sha_air::{get_random_message, Sha256Config, Sha512Config}; +use openvm_sha_air::{get_random_message, Sha256Config, Sha384Config, Sha512Config}; 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}; @@ -122,6 +122,11 @@ fn rand_sha512_test() { rand_sha_test::(SHA512); } +#[test] +fn rand_sha384_test() { + rand_sha_test::(SHA384); +} + /////////////////////////////////////////////////////////////////////////////////////// /// SANITY TESTS /// @@ -170,6 +175,11 @@ fn sha512_roundtrip_sanity_test() { execute_roundtrip_sanity_test::(SHA512); } +#[test] +fn sha384_roundtrip_sanity_test() { + execute_roundtrip_sanity_test::(SHA384); +} + #[test] fn sha256_solve_sanity_check() { let input = b"Axiom is the best! Axiom is the best! Axiom is the best! Axiom is the best!"; @@ -180,3 +190,29 @@ fn sha256_solve_sanity_check() { ]; assert_eq!(output, expected); } + +#[test] +fn sha512_solve_sanity_check() { + let input = b"Axiom is the best! Axiom is the best! Axiom is the best! Axiom is the best!"; + let output = sha2_solve::(input); + // verified manually against the sha512 command line tool + let expected: [u8; 64] = [ + 0, 8, 195, 142, 70, 71, 97, 208, 132, 132, 243, 53, 179, 186, 8, 162, 71, 75, 126, 21, 130, + 203, 245, 126, 207, 65, 119, 60, 64, 79, 200, 2, 194, 17, 189, 137, 164, 213, 107, 197, + 152, 11, 242, 165, 146, 80, 96, 105, 249, 27, 139, 14, 244, 21, 118, 31, 94, 87, 32, 145, + 149, 98, 235, 75, + ]; + assert_eq!(output, expected); +} + +#[test] +fn sha384_solve_sanity_check() { + let input = b"Axiom is the best! Axiom is the best! Axiom is the best! Axiom is the best!"; + let output = sha2_solve::(input); + let expected: [u8; 48] = [ + 134, 227, 167, 229, 35, 110, 115, 174, 10, 27, 197, 116, 56, 144, 150, 36, 152, 190, 212, + 120, 26, 243, 125, 4, 2, 60, 164, 195, 218, 219, 255, 143, 240, 75, 158, 126, 102, 105, 8, + 202, 142, 240, 230, 161, 162, 152, 111, 71, + ]; + assert_eq!(output, expected); +} diff --git a/extensions/sha256/circuit/src/sha256_chip/trace.rs b/extensions/sha256/circuit/src/sha256_chip/trace.rs index 26474f9a32..35b064124d 100644 --- a/extensions/sha256/circuit/src/sha256_chip/trace.rs +++ b/extensions/sha256/circuit/src/sha256_chip/trace.rs @@ -311,7 +311,7 @@ where .zip(writes_aux.prev_data()) .for_each(|(x, y)| *x = *y); } - Sha2Variant::Sha512 => { + Sha2Variant::Sha512 | Sha2Variant::Sha384 => { debug_assert_eq!(C::NUM_WRITES, 2); debug_assert_eq!(digest_writes.len(), 2); debug_assert_eq!(cols.writes_aux_base.len(), 2); diff --git a/extensions/sha256/guest/src/lib.rs b/extensions/sha256/guest/src/lib.rs index 53b60e8bc3..6e88ad9b24 100644 --- a/extensions/sha256/guest/src/lib.rs +++ b/extensions/sha256/guest/src/lib.rs @@ -9,6 +9,7 @@ pub const SHA2_FUNCT3: u8 = 0b100; pub enum Sha2BaseFunct7 { Sha256 = 0x1, Sha512 = 0x2, + Sha384 = 0x3, } /// The sha256 cryptographic hash function. @@ -27,6 +28,14 @@ pub fn sha512(input: &[u8]) -> [u8; 64] { output } +/// The sha384 cryptographic hash function. +#[inline(always)] +pub fn sha384(input: &[u8]) -> [u8; 48] { + let mut output = [0u8; 64]; + set_sha384(input, &mut output); + output[..48].try_into().unwrap() +} + /// zkvm native implementation of sha256 /// # Safety /// @@ -59,6 +68,24 @@ extern "C" fn zkvm_sha512_impl(bytes: *const u8, len: usize, output: *mut u8) { openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA2_FUNCT3, funct7 = Sha2BaseFunct7::Sha512 as u8, rd = In output, rs1 = In bytes, rs2 = In len); } +/// zkvm native implementation of sha384 +/// # Safety +/// +/// The VM accepts the preimage by pointer and length, and writes the +/// 48-byte hash. +/// - `bytes` must point to an input buffer at least `len` long. +/// - `output` must point to a buffer that is at least 64-bytes long. +/// The first 48 bytes written will be the SHA-384 digest. +/// The last 16 bytes are zeros. +/// +/// [`sha2-384`]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf +#[cfg(target_os = "zkvm")] +#[inline(always)] +#[no_mangle] +extern "C" fn zkvm_sha384_impl(bytes: *const u8, len: usize, output: *mut u8) { + openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA2_FUNCT3, funct7 = Sha2BaseFunct7::Sha384 as u8, rd = In output, rs1 = In bytes, rs2 = In len); +} + /// Sets `output` to the sha256 hash of `input`. pub fn set_sha256(input: &[u8], output: &mut [u8; 32]) { #[cfg(not(target_os = "zkvm"))] @@ -88,3 +115,20 @@ pub fn set_sha512(input: &[u8], output: &mut [u8; 64]) { zkvm_sha512_impl(input.as_ptr(), input.len(), output.as_mut_ptr() as *mut u8); } } + +/// Sets the first 48 bytes of `output` to the sha384 hash of `input`. +/// Sets the last 16 bytes to zeros. +pub fn set_sha384(input: &[u8], output: &mut [u8; 64]) { + #[cfg(not(target_os = "zkvm"))] + { + use sha2::{Digest, Sha384}; + let mut hasher = Sha384::new(); + hasher.update(input); + output[..48].copy_from_slice(hasher.finalize().as_ref()); + output[48..].fill(0); + } + #[cfg(target_os = "zkvm")] + { + zkvm_sha384_impl(input.as_ptr(), input.len(), output.as_mut_ptr() as *mut u8); + } +} diff --git a/extensions/sha256/tests/programs/examples/sha.rs b/extensions/sha256/tests/programs/examples/sha.rs index 45be16d5d6..833649465a 100644 --- a/extensions/sha256/tests/programs/examples/sha.rs +++ b/extensions/sha256/tests/programs/examples/sha.rs @@ -7,7 +7,7 @@ use alloc::vec::Vec; use core::hint::black_box; use hex::FromHex; -use openvm_sha256_guest::{sha256, sha512}; +use openvm_sha256_guest::{sha256, sha384, sha512}; openvm::entry!(main); @@ -15,6 +15,7 @@ struct ShaTestVector { input: &'static str, expected_output_sha256: &'static str, expected_output_sha512: &'static str, + expected_output_sha384: &'static str, } pub fn main() { @@ -23,21 +24,25 @@ pub fn main() { input: "", expected_output_sha256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", expected_output_sha512: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + expected_output_sha384: "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", }, ShaTestVector { input: "98c1c0bdb7d5fea9a88859f06c6c439f", expected_output_sha256: "b6b2c9c9b6f30e5c66c977f1bd7ad97071bee739524aecf793384890619f2b05", expected_output_sha512: "eb576959c531f116842c0cc915a29c8f71d7a285c894c349b83469002ef093d51f9f14ce4248488bff143025e47ed27c12badb9cd43779cb147408eea062d583", + expected_output_sha384: "63e3061aab01f335ea3a4e617b9d14af9b63a5240229164ee962f6d5335ff25f0f0bf8e46723e83c41b9d17413b6a3c7", }, ShaTestVector { input: "5b58f4163e248467cc1cd3eecafe749e8e2baaf82c0f63af06df0526347d7a11327463c115210a46b6740244eddf370be89c", expected_output_sha256: "ac0e25049870b91d78ef6807bb87fce4603c81abd3c097fba2403fd18b6ce0b7", expected_output_sha512: "a20d5fb14814d045a7d2861e80d2b688f1cd1daaba69e6bb1cc5233f514141ea4623b3373af702e78e3ec5dc8c1b716a37a9a2f5fbc9493b9df7043f5e99a8da", + expected_output_sha384: "eac4b72b0540486bc088834860873338e31e9e4062532bf509191ef63b9298c67db5654a28fe6f07e4cc6ff466d1be24", }, ShaTestVector { input: "9ad198539e3160194f38ac076a782bd5210a007560d1fce9ef78f8a4a5e4d78c6b96c250cff3520009036e9c6087d5dab587394edda862862013de49a12072485a6c01165ec0f28ffddf1873fbd53e47fcd02fb6a5ccc9622d5588a92429c663ce298cb71b50022fc2ec4ba9f5bbd250974e1a607b165fee16e8f3f2be20d7348b91a2f518ce928491900d56d9f86970611580350cee08daea7717fe28a73b8dcfdea22a65ed9f5a09198de38e4e4f2cc05b0ba3dd787a5363ab6c9f39dcb66c1a29209b1d6b1152769395df8150b4316658ea6ab19af94903d643fcb0ae4d598035ebe73c8b1b687df1ab16504f633c929569c6d0e5fae6eea43838fbc8ce2c2b43161d0addc8ccf945a9c4e06294e56a67df0000f561f61b630b1983ba403e775aaeefa8d339f669d1e09ead7eae979383eda983321e1743e5404b4b328da656de79ff52d179833a6bd5129f49432d74d001996c37c68d9ab49fcff8061d193576f396c20e1f0d9ee83a51290ba60efa9c3cb2e15b756321a7ca668cdbf63f95ec33b1c450aa100101be059dc00077245b25a6a66698dee81953ed4a606944076e2858b1420de0095a7f60b08194d6d9a997009d345c71f63a7034b976e409af8a9a040ac7113664609a7adedb76b2fadf04b0348392a1650526eb2a4d6ed5e4bbcda8aabc8488b38f4f5d9a398103536bb8250ed82a9b9825f7703c263f9e", expected_output_sha256: "080ad71239852124fc26758982090611b9b19abf22d22db3a57f67a06e984a23", expected_output_sha512: "8d215ee6dc26757c210db0dd00c1c6ed16cc34dbd4bb0fa10c1edb6b62d5ab16aea88c881001b173d270676daf2d6381b5eab8711fa2f5589c477c1d4b84774f", + expected_output_sha384: "904a90010d772a904a35572fdd4bdf1dd253742e47872c8a18e2255f66fa889e44781e65487a043f435daa53c496a53e", } ]; @@ -47,6 +52,7 @@ pub fn main() { input, expected_output_sha256, expected_output_sha512, + expected_output_sha384, }, ) in test_vectors.iter().enumerate() { @@ -67,5 +73,13 @@ pub fn main() { input, expected_output_sha512, output ); } + let expected_output_sha384 = Vec::from_hex(expected_output_sha384).unwrap(); + let output = sha384(black_box(&input)); + if output != *expected_output_sha384 { + panic!( + "sha384 test {i} failed on input: {:?}.\nexpected: {:?},\ngot: {:?}", + input, expected_output_sha384, output + ); + } } } diff --git a/extensions/sha256/transpiler/src/lib.rs b/extensions/sha256/transpiler/src/lib.rs index a78ec612bf..532e3d2828 100644 --- a/extensions/sha256/transpiler/src/lib.rs +++ b/extensions/sha256/transpiler/src/lib.rs @@ -14,6 +14,7 @@ use strum::{EnumCount, EnumIter, FromRepr}; pub enum Rv32Sha2Opcode { SHA256, SHA512, + SHA384, } #[derive(Default)] @@ -49,6 +50,14 @@ impl TranspilerExtension for Sha2TranspilerExtension { true, ); Some(TranspilerOutput::one_to_one(instruction)) + } else if dec_insn.funct7 == Sha2BaseFunct7::Sha384 as u32 { + let instruction = from_r_type( + Rv32Sha2Opcode::SHA384.global_opcode().as_usize(), + RV32_MEMORY_AS as usize, + &dec_insn, + true, + ); + Some(TranspilerOutput::one_to_one(instruction)) } else { None } From 00b71ea468baa3e5a325746183713ecc0b043e34 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 4 Apr 2025 16:42:21 -0400 Subject: [PATCH 13/27] Fix rebase issue --- .github/workflows/primitives.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/primitives.yml b/.github/workflows/primitives.yml index 714230b8cd..ae4d0b63dd 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/**" - "crates/circuits/mod-builder/**" - "Cargo.toml" - ".github/workflows/primitives.yml" @@ -47,8 +47,8 @@ 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 From e927567c1b9db73de8e8569d575408b2ec07e346 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 4 Apr 2025 16:57:23 -0400 Subject: [PATCH 14/27] fix lint errors --- crates/circuits/sha-air/src/tests.rs | 6 ++++-- crates/circuits/sha-macros/Cargo.toml | 4 +++- crates/circuits/sha-macros/src/lib.rs | 15 ++++++++------- .../circuits/sha-macros/tests/aligned_borrow.rs | 3 ++- crates/circuits/sha-macros/tests/arrays.rs | 1 + .../circuits/sha-macros/tests/const-len-arrays.rs | 3 ++- crates/circuits/sha-macros/tests/nested.rs | 6 ++++-- crates/circuits/sha-macros/tests/simple.rs | 1 + extensions/sha256/circuit/Cargo.toml | 6 ++++-- extensions/sha256/circuit/src/extension.rs | 3 --- extensions/sha256/circuit/src/sha256_chip/air.rs | 3 +-- extensions/sha256/circuit/src/sha256_chip/mod.rs | 3 --- .../sha256/circuit/src/sha256_chip/tests.rs | 2 -- .../sha256/circuit/src/sha256_chip/trace.rs | 8 +++----- 14 files changed, 33 insertions(+), 31 deletions(-) diff --git a/crates/circuits/sha-air/src/tests.rs b/crates/circuits/sha-air/src/tests.rs index cf40d411d8..8832a976e3 100644 --- a/crates/circuits/sha-air/src/tests.rs +++ b/crates/circuits/sha-air/src/tests.rs @@ -1,4 +1,3 @@ -use crate::{Sha384Config, ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut}; use std::{borrow::BorrowMut, cmp::max, sync::Arc}; use openvm_circuit::arch::{ @@ -22,7 +21,10 @@ use openvm_stark_backend::{ use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; -use crate::{compose, small_sig0_field, Sha256Config, Sha2Air, Sha512Config, ShaConfig}; +use crate::{ + compose, small_sig0_field, Sha256Config, Sha2Air, Sha384Config, Sha512Config, ShaConfig, + ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut, +}; // A wrapper AIR purely for testing purposes #[derive(Clone, Debug)] diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml index c926edf248..9db0ecc353 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/sha-macros/Cargo.toml @@ -11,7 +11,6 @@ syn = { version = "2.0", features = ["full", "extra-traits"] } quote = "1.0" itertools = "0.14" proc-macro2 = "1.0" -ndarray = "0.16" [dev-dependencies] openvm-sha-air = { workspace = true } @@ -20,3 +19,6 @@ ndarray.workspace = true [lib] proc-macro = true + +[package.metadata.cargo-shear] +ignored = ["ndarray"] \ No newline at end of file diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/sha-macros/src/lib.rs index ecb5141c66..7d59b42cfe 100644 --- a/crates/circuits/sha-macros/src/lib.rs +++ b/crates/circuits/sha-macros/src/lib.rs @@ -25,13 +25,14 @@ pub fn cols_ref(input: TokenStream) -> TokenStream { let span = derive_input.ident.span(); let res = cols_ref_impl(derive_input, config); - if res.is_err() { - syn::Error::new(span, res.err().unwrap().to_string()) - .to_compile_error() - .into() - } else { - res.unwrap().into() - } + res.map_or_else( + |err| { + syn::Error::new(span, err.to_string()) + .to_compile_error() + .into() + }, + |ok| ok.into(), + ) } fn cols_ref_impl( diff --git a/crates/circuits/sha-macros/tests/aligned_borrow.rs b/crates/circuits/sha-macros/tests/aligned_borrow.rs index 65fdab5e49..3dc51112f2 100644 --- a/crates/circuits/sha-macros/tests/aligned_borrow.rs +++ b/crates/circuits/sha-macros/tests/aligned_borrow.rs @@ -4,6 +4,7 @@ use openvm_sha_macros::ColsRef; mod test_config; use test_config::{TestConfig, TestConfigImpl}; +#[allow(dead_code)] #[derive(ColsRef)] #[config(TestConfig)] struct TestCols { @@ -47,7 +48,7 @@ fn plain_from_mut() { test.a[0] = 1; test.b.a = 1; test.b.b[0] = 1; - let test2: TestColsRef = TestColsRef::from_mut::(&mut test); + let test2: TestColsRef = TestColsRef::from_mut::(&test); println!("{}", test2.a); println!("{:?}", test2.b); } diff --git a/crates/circuits/sha-macros/tests/arrays.rs b/crates/circuits/sha-macros/tests/arrays.rs index 32a0a4c4d8..e49f67bb69 100644 --- a/crates/circuits/sha-macros/tests/arrays.rs +++ b/crates/circuits/sha-macros/tests/arrays.rs @@ -3,6 +3,7 @@ use openvm_sha_macros::ColsRef; mod test_config; use test_config::{TestConfig, TestConfigImpl}; +#[allow(dead_code)] #[derive(ColsRef)] #[config(TestConfig)] struct ArrayTest { diff --git a/crates/circuits/sha-macros/tests/const-len-arrays.rs b/crates/circuits/sha-macros/tests/const-len-arrays.rs index 671c65a88f..df7214a5ec 100644 --- a/crates/circuits/sha-macros/tests/const-len-arrays.rs +++ b/crates/circuits/sha-macros/tests/const-len-arrays.rs @@ -7,6 +7,7 @@ const THREE: usize = 3; mod test_config; use test_config::{TestConfig, TestConfigImpl}; +#[allow(dead_code)] #[derive(ColsRef)] #[config(TestConfig)] struct ConstLenArrayTest { @@ -18,7 +19,7 @@ struct ConstLenArrayTest { #[test] fn const_len_arrays() { - let input = [1; 1 + TestConfigImpl::N * 2 + 1 * 2 * 3]; + let input = [1; 1 + TestConfigImpl::N * 2 + 2 * 3]; let test: ConstLenArrayTestRef = ConstLenArrayTestRef::from::(&input); println!("{}", test.a); println!("{}", test.b); diff --git a/crates/circuits/sha-macros/tests/nested.rs b/crates/circuits/sha-macros/tests/nested.rs index 53d89ed521..6b45fa98bb 100644 --- a/crates/circuits/sha-macros/tests/nested.rs +++ b/crates/circuits/sha-macros/tests/nested.rs @@ -1,6 +1,7 @@ use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; +#[allow(dead_code)] #[derive(ColsRef)] #[config(ShaConfig)] struct Test1Cols { @@ -8,6 +9,7 @@ struct Test1Cols { pub nested: Test2Cols, } +#[allow(dead_code)] #[derive(ColsRef)] #[config(ShaConfig)] struct Test2Cols { @@ -34,8 +36,8 @@ fn nested_mut() { #[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); + let mut_test: Test1ColsRefMut = Test1ColsRefMut::from::(&mut mut_input); + let const_test: Test1ColsRef = Test1ColsRef::from_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 index 4de63105a4..39543167f5 100644 --- a/crates/circuits/sha-macros/tests/simple.rs +++ b/crates/circuits/sha-macros/tests/simple.rs @@ -1,6 +1,7 @@ use openvm_sha_air::{Sha256Config, ShaConfig}; use openvm_sha_macros::ColsRef; +#[allow(dead_code)] #[derive(ColsRef)] #[config(ShaConfig)] struct Test { diff --git a/extensions/sha256/circuit/Cargo.toml b/extensions/sha256/circuit/Cargo.toml index 5a45bc4d0c..7425f12842 100644 --- a/extensions/sha256/circuit/Cargo.toml +++ b/extensions/sha256/circuit/Cargo.toml @@ -23,8 +23,7 @@ derive_more = { workspace = true, features = ["from"] } rand.workspace = true serde.workspace = true sha2 = { version = "0.10", default-features = false } -strum = { workspace = true } -ndarray.workspace = true +ndarray = { workspace = true, default-features = false } [dev-dependencies] openvm-stark-sdk = { workspace = true } @@ -39,3 +38,6 @@ mimalloc = ["openvm-circuit/mimalloc"] jemalloc = ["openvm-circuit/jemalloc"] jemalloc-prof = ["openvm-circuit/jemalloc-prof"] nightly-features = ["openvm-circuit/nightly-features"] + +[package.metadata.cargo-shear] +ignored = ["ndarray"] \ No newline at end of file diff --git a/extensions/sha256/circuit/src/extension.rs b/extensions/sha256/circuit/src/extension.rs index f95b3215eb..55954693b2 100644 --- a/extensions/sha256/circuit/src/extension.rs +++ b/extensions/sha256/circuit/src/extension.rs @@ -88,7 +88,6 @@ impl VmExtension for Sha2 { builder.system_config().memory_config.pointer_max_bits, bitwise_lu_chip.clone(), builder.new_bus_idx(), - Rv32Sha2Opcode::CLASS_OFFSET, builder.system_base().offline_memory(), ); inventory.add_executor(sha256_chip, vec![Rv32Sha2Opcode::SHA256.global_opcode()])?; @@ -98,7 +97,6 @@ impl VmExtension for Sha2 { builder.system_config().memory_config.pointer_max_bits, bitwise_lu_chip.clone(), builder.new_bus_idx(), - Rv32Sha2Opcode::CLASS_OFFSET, builder.system_base().offline_memory(), ); inventory.add_executor(sha512_chip, vec![Rv32Sha2Opcode::SHA512.global_opcode()])?; @@ -108,7 +106,6 @@ impl VmExtension for Sha2 { builder.system_config().memory_config.pointer_max_bits, bitwise_lu_chip, builder.new_bus_idx(), - Rv32Sha2Opcode::CLASS_OFFSET, builder.system_base().offline_memory(), ); inventory.add_executor(sha384_chip, vec![Rv32Sha2Opcode::SHA384.global_opcode()])?; diff --git a/extensions/sha256/circuit/src/sha256_chip/air.rs b/extensions/sha256/circuit/src/sha256_chip/air.rs index e6c9a6863c..e48991d5ac 100644 --- a/extensions/sha256/circuit/src/sha256_chip/air.rs +++ b/extensions/sha256/circuit/src/sha256_chip/air.rs @@ -1,5 +1,4 @@ -use std::cmp::min; -use std::convert::TryInto; +use std::{cmp::min, convert::TryInto}; use openvm_circuit::{ arch::ExecutionBridge, diff --git a/extensions/sha256/circuit/src/sha256_chip/mod.rs b/extensions/sha256/circuit/src/sha256_chip/mod.rs index 61e8d14293..3fcd181edf 100644 --- a/extensions/sha256/circuit/src/sha256_chip/mod.rs +++ b/extensions/sha256/circuit/src/sha256_chip/mod.rs @@ -41,7 +41,6 @@ pub struct Sha2VmChip { pub records: Vec>, pub offline_memory: Arc>>, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, - offset: usize, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] @@ -65,7 +64,6 @@ impl Sha2VmChip { address_bits: usize, bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, self_bus_idx: BusIndex, - offset: usize, offline_memory: Arc>>, ) -> Self { Self { @@ -79,7 +77,6 @@ impl Sha2VmChip { ), bitwise_lookup_chip, records: Vec::new(), - offset, offline_memory, } } diff --git a/extensions/sha256/circuit/src/sha256_chip/tests.rs b/extensions/sha256/circuit/src/sha256_chip/tests.rs index 09ef237b33..92bbcb8185 100644 --- a/extensions/sha256/circuit/src/sha256_chip/tests.rs +++ b/extensions/sha256/circuit/src/sha256_chip/tests.rs @@ -99,7 +99,6 @@ fn rand_sha_test(opcode: Rv32Sha2Opcode) { tester.address_bits(), bitwise_chip.clone(), BUS_IDX, - Rv32Sha2Opcode::CLASS_OFFSET, tester.offline_memory_mutex_arc(), ); @@ -146,7 +145,6 @@ fn execute_roundtrip_sanity_test(opcode: Rv32Sha2Opcode) { tester.address_bits(), bitwise_chip.clone(), BUS_IDX, - Rv32Sha2Opcode::CLASS_OFFSET, tester.offline_memory_mutex_arc(), ); diff --git a/extensions/sha256/circuit/src/sha256_chip/trace.rs b/extensions/sha256/circuit/src/sha256_chip/trace.rs index 35b064124d..92798ca846 100644 --- a/extensions/sha256/circuit/src/sha256_chip/trace.rs +++ b/extensions/sha256/circuit/src/sha256_chip/trace.rs @@ -316,7 +316,7 @@ where debug_assert_eq!(digest_writes.len(), 2); debug_assert_eq!(cols.writes_aux_base.len(), 2); debug_assert_eq!(cols.writes_aux_prev_data.nrows(), 2); - for i in 0..C::NUM_WRITES { + for (i, digest_write) in digest_writes.iter().enumerate() { let prev_data = cols.writes_aux_prev_data.row(i).to_vec(); // write to a temporary MemoryWriteAuxCols object and then copy it over to the columns struct @@ -327,10 +327,8 @@ where cols.writes_aux_base[i], prev_data.try_into().unwrap(), ); - memory_aux_cols_factory.generate_write_aux( - digest_writes[i], - &mut writes_aux, - ); + memory_aux_cols_factory + .generate_write_aux(digest_write, &mut writes_aux); cols.writes_aux_base[i] = writes_aux.get_base(); cols.writes_aux_prev_data .row_mut(i) From e27df873f84801a3c7e78e18fe8dd8bcdce79ae3 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Fri, 4 Apr 2025 18:39:13 -0400 Subject: [PATCH 15/27] Rename SHA-256 to SHA-2 --- .github/workflows/extension-tests.yml | 2 +- .github/workflows/primitives.yml | 6 +-- Cargo.toml | 18 ++++----- benchmarks/programs/kitchen-sink/Cargo.toml | 2 +- benchmarks/programs/kitchen-sink/src/main.rs | 2 +- benchmarks/src/bin/kitchen_sink.rs | 2 +- book/src/custom-extensions/overview.md | 4 +- .../custom-extensions/{sha256.md => sha2.md} | 0 crates/circuits/sha-macros/Cargo.toml | 2 +- crates/circuits/sha-macros/tests/flags.rs | 4 +- crates/circuits/sha-macros/tests/nested.rs | 6 +-- crates/circuits/sha-macros/tests/simple.rs | 4 +- crates/circuits/sha-macros/tests/work-vars.rs | 4 +- .../circuits/{sha-air => sha2-air}/Cargo.toml | 2 +- .../circuits/{sha-air => sha2-air}/src/air.rs | 12 +++--- .../{sha-air => sha2-air}/src/columns.rs | 30 +++++++------- .../{sha-air => sha2-air}/src/config.rs | 8 ++-- .../circuits/{sha-air => sha2-air}/src/lib.rs | 0 .../{sha-air => sha2-air}/src/tests.rs | 30 +++++++------- .../{sha-air => sha2-air}/src/trace.rs | 8 ++-- .../{sha-air => sha2-air}/src/utils.rs | 36 ++++++++--------- crates/sdk/Cargo.toml | 4 +- crates/sdk/src/config/global.rs | 10 ++--- docs/specs/circuit.md | 2 +- docs/specs/isa-table.md | 4 +- examples/sha2/Cargo.toml | 19 +++++++++ examples/{sha256 => sha2}/openvm.toml | 0 examples/sha2/src/main.rs | 39 +++++++++++++++++++ examples/sha256/Cargo.toml | 17 -------- examples/sha256/src/main.rs | 25 ------------ .../{sha256 => sha2}/circuit/Cargo.toml | 8 ++-- extensions/{sha256 => sha2}/circuit/README.md | 4 +- .../{sha256 => sha2}/circuit/src/extension.rs | 4 +- extensions/sha2/circuit/src/lib.rs | 5 +++ .../circuit/src/sha2_chip}/air.rs | 26 ++++++------- .../circuit/src/sha2_chip}/columns.rs | 12 +++--- .../circuit/src/sha2_chip}/config.rs | 14 +++---- .../circuit/src/sha2_chip}/mod.rs | 4 +- .../circuit/src/sha2_chip}/tests.rs | 14 +++---- .../circuit/src/sha2_chip}/trace.rs | 14 ++++--- extensions/{sha256 => sha2}/circuit/tmp.rs | 0 extensions/{sha256 => sha2}/guest/Cargo.toml | 4 +- extensions/{sha256 => sha2}/guest/src/lib.rs | 0 extensions/{sha256 => sha2}/tests/Cargo.toml | 8 ++-- .../tests/programs/Cargo.toml | 4 +- .../tests/programs/examples/sha.rs | 2 +- extensions/{sha256 => sha2}/tests/src/lib.rs | 4 +- .../{sha256 => sha2}/transpiler/Cargo.toml | 6 +-- .../{sha256 => sha2}/transpiler/src/lib.rs | 2 +- extensions/sha256/circuit/src/lib.rs | 5 --- 50 files changed, 231 insertions(+), 211 deletions(-) rename book/src/custom-extensions/{sha256.md => sha2.md} (100%) rename crates/circuits/{sha-air => sha2-air}/Cargo.toml (95%) rename crates/circuits/{sha-air => sha2-air}/src/air.rs (98%) rename crates/circuits/{sha-air => sha2-air}/src/columns.rs (88%) rename crates/circuits/{sha-air => sha2-air}/src/config.rs (98%) rename crates/circuits/{sha-air => sha2-air}/src/lib.rs (100%) rename crates/circuits/{sha-air => sha2-air}/src/tests.rs (90%) rename crates/circuits/{sha-air => sha2-air}/src/trace.rs (99%) rename crates/circuits/{sha-air => sha2-air}/src/utils.rs (87%) create mode 100644 examples/sha2/Cargo.toml rename examples/{sha256 => sha2}/openvm.toml (100%) create mode 100644 examples/sha2/src/main.rs delete mode 100644 examples/sha256/Cargo.toml delete mode 100644 examples/sha256/src/main.rs rename extensions/{sha256 => sha2}/circuit/Cargo.toml (88%) rename extensions/{sha256 => sha2}/circuit/README.md (98%) rename extensions/{sha256 => sha2}/circuit/src/extension.rs (97%) create mode 100644 extensions/sha2/circuit/src/lib.rs rename extensions/{sha256/circuit/src/sha256_chip => sha2/circuit/src/sha2_chip}/air.rs (96%) rename extensions/{sha256/circuit/src/sha256_chip => sha2/circuit/src/sha2_chip}/columns.rs (94%) rename extensions/{sha256/circuit/src/sha256_chip => sha2/circuit/src/sha2_chip}/config.rs (87%) rename extensions/{sha256/circuit/src/sha256_chip => sha2/circuit/src/sha2_chip}/mod.rs (99%) rename extensions/{sha256/circuit/src/sha256_chip => sha2/circuit/src/sha2_chip}/tests.rs (94%) rename extensions/{sha256/circuit/src/sha256_chip => sha2/circuit/src/sha2_chip}/trace.rs (97%) rename extensions/{sha256 => sha2}/circuit/tmp.rs (100%) rename extensions/{sha256 => sha2}/guest/Cargo.toml (79%) rename extensions/{sha256 => sha2}/guest/src/lib.rs (100%) rename extensions/{sha256 => sha2}/tests/Cargo.toml (74%) rename extensions/{sha256 => sha2}/tests/programs/Cargo.toml (88%) rename extensions/{sha256 => sha2}/tests/programs/examples/sha.rs (98%) rename extensions/{sha256 => sha2}/tests/src/lib.rs (90%) rename extensions/{sha256 => sha2}/transpiler/Cargo.toml (73%) rename extensions/{sha256 => sha2}/transpiler/src/lib.rs (97%) delete mode 100644 extensions/sha256/circuit/src/lib.rs diff --git a/.github/workflows/extension-tests.yml b/.github/workflows/extension-tests.yml index bb251817d1..43ebfa5320 100644 --- a/.github/workflows/extension-tests.yml +++ b/.github/workflows/extension-tests.yml @@ -28,7 +28,7 @@ jobs: - { name: "rv32im", path: "rv32im" } - { name: "native", path: "native" } - { name: "keccak256", path: "keccak256" } - - { name: "sha256", path: "sha256" } + - { name: "sha2", path: "sha2" } - { name: "bigint", path: "bigint" } - { name: "algebra", path: "algebra" } - { name: "ecc", path: "ecc" } diff --git a/.github/workflows/primitives.yml b/.github/workflows/primitives.yml index ae4d0b63dd..d020aa0d2b 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/sha-air/**" + - "crates/circuits/sha2-air/**" - "crates/circuits/mod-builder/**" - "Cargo.toml" - ".github/workflows/primitives.yml" @@ -47,8 +47,8 @@ jobs: run: | cargo nextest run --cargo-profile fast --features parallel - - name: Run tests for sha-air - working-directory: crates/circuits/sha-air + - name: Run tests for sha2-air + working-directory: crates/circuits/sha2-air run: | cargo nextest run --cargo-profile fast --features parallel diff --git a/Cargo.toml b/Cargo.toml index e71940a96d..1a201042b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,10 +51,10 @@ members = [ "extensions/keccak256/transpiler", "extensions/keccak256/guest", "extensions/keccak256/tests", - "extensions/sha256/circuit", - "extensions/sha256/transpiler", - "extensions/sha256/guest", - "extensions/sha256/tests", + "extensions/sha2/circuit", + "extensions/sha2/transpiler", + "extensions/sha2/guest", + "extensions/sha2/tests", "extensions/ecc/circuit", "extensions/ecc/transpiler", "extensions/ecc/guest", @@ -112,7 +112,7 @@ openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", ta 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-sha-air = { path = "crates/circuits/sha-air", default-features = false } +openvm-sha2-air = { path = "crates/circuits/sha2-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 } @@ -141,9 +141,9 @@ openvm-native-recursion = { path = "extensions/native/recursion", default-featur openvm-keccak256-circuit = { path = "extensions/keccak256/circuit", default-features = false } openvm-keccak256-transpiler = { path = "extensions/keccak256/transpiler", default-features = false } openvm-keccak256-guest = { path = "extensions/keccak256/guest", default-features = false } -openvm-sha256-circuit = { path = "extensions/sha256/circuit", default-features = false } -openvm-sha256-transpiler = { path = "extensions/sha256/transpiler", default-features = false } -openvm-sha256-guest = { path = "extensions/sha256/guest", default-features = false } +openvm-sha2-circuit = { path = "extensions/sha2/circuit", default-features = false } +openvm-sha2-transpiler = { path = "extensions/sha2/transpiler", default-features = false } +openvm-sha2-guest = { path = "extensions/sha2/guest", default-features = false } openvm-bigint-circuit = { path = "extensions/bigint/circuit", default-features = false } openvm-bigint-transpiler = { path = "extensions/bigint/transpiler", default-features = false } openvm-bigint-guest = { path = "extensions/bigint/guest", default-features = false } @@ -212,7 +212,7 @@ rrs-lib = "0.1.0" rand = { version = "0.8.5", default-features = false } hex = { version = "0.4.3", default-features = false } serde-big-array = "0.5.1" -ndarray = "0.16.1" +ndarray = { version = "0.16.1", default-features = false } # default-features = false for no_std for use in guest programs itertools = { version = "0.14.0", default-features = false } diff --git a/benchmarks/programs/kitchen-sink/Cargo.toml b/benchmarks/programs/kitchen-sink/Cargo.toml index af853486cf..fe376068e4 100644 --- a/benchmarks/programs/kitchen-sink/Cargo.toml +++ b/benchmarks/programs/kitchen-sink/Cargo.toml @@ -18,7 +18,7 @@ openvm-pairing-guest = { path = "../../../extensions/pairing/guest", default-fea "bls12_381", ] } openvm-keccak256-guest = { path = "../../../extensions/keccak256/guest", default-features = false } -openvm-sha256-guest = { path = "../../../extensions/sha256/guest", default-features = false } +openvm-sha2-guest = { path = "../../../extensions/sha2/guest", default-features = false } openvm-bigint-guest = { path = "../../../extensions/bigint/guest", default-features = false } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } serde = "1.0" diff --git a/benchmarks/programs/kitchen-sink/src/main.rs b/benchmarks/programs/kitchen-sink/src/main.rs index 8c12e165f7..2dd0afdaa7 100644 --- a/benchmarks/programs/kitchen-sink/src/main.rs +++ b/benchmarks/programs/kitchen-sink/src/main.rs @@ -3,7 +3,7 @@ use std::{hint::black_box, mem::transmute}; use openvm_algebra_guest::IntMod; use openvm_bigint_guest::I256; use openvm_keccak256_guest::keccak256; -use openvm_sha256_guest::sha256; +use openvm_sha2_guest::sha256; #[allow(unused_imports)] use { openvm_ecc_guest::{ diff --git a/benchmarks/src/bin/kitchen_sink.rs b/benchmarks/src/bin/kitchen_sink.rs index 9ec4a26d71..053531d365 100644 --- a/benchmarks/src/bin/kitchen_sink.rs +++ b/benchmarks/src/bin/kitchen_sink.rs @@ -30,7 +30,7 @@ fn main() -> Result<()> { .rv32m(Default::default()) .io(Default::default()) .keccak(Default::default()) - .sha256(Default::default()) + .sha2(Default::default()) .bigint(Default::default()) .modular(ModularExtension::new(vec![ BigUint::from_str("1000000000000000003").unwrap(), diff --git a/book/src/custom-extensions/overview.md b/book/src/custom-extensions/overview.md index aecbdf5f36..bfc59f1e55 100644 --- a/book/src/custom-extensions/overview.md +++ b/book/src/custom-extensions/overview.md @@ -5,13 +5,13 @@ You can seamlessly integrate certain performance-optimized extensions maintained In this chapter, we will explain how to use the following existing extensions: - [`openvm-keccak-guest`](./keccak.md) - Keccak256 hash function. -- [`openvm-sha256-guest`](./sha256.md) - SHA2-256 hash function. +- [`openvm-sha2-guest`](./sha2.md) - SHA2 hash functions. - [`openvm-bigint-guest`](./bigint.md) - Big integer arithmetic for 256-bit signed and unsigned integers. - [`openvm-algebra-guest`](./algebra.md) - Modular arithmetic and complex field extensions. - [`openvm-ecc-guest`](./ecc.md) - Elliptic curve cryptography. - [`openvm-pairing-guest`](./pairing.md) - Elliptic curve optimal Ate pairings. -Some extensions such as `openvm-keccak-guest`, `openvm-sha256-guest`, and `openvm-bigint-guest` can be enabled without specifying any additional configuration. +Some extensions such as `openvm-keccak-guest`, `openvm-sha2-guest`, and `openvm-bigint-guest` can be enabled without specifying any additional configuration. On the other hand certain arithmetic operations, particularly modular arithmetic, can be optimized significantly when the modulus is known at compile time. This approach requires a framework to inform the compiler about all the moduli and associated arithmetic structures we intend to use. To achieve this, three steps are involved: diff --git a/book/src/custom-extensions/sha256.md b/book/src/custom-extensions/sha2.md similarity index 100% rename from book/src/custom-extensions/sha256.md rename to book/src/custom-extensions/sha2.md diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/sha-macros/Cargo.toml index 9db0ecc353..1abe551abd 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/sha-macros/Cargo.toml @@ -13,7 +13,7 @@ itertools = "0.14" proc-macro2 = "1.0" [dev-dependencies] -openvm-sha-air = { workspace = true } +openvm-sha2-air = { workspace = true } openvm-circuit-primitives-derive = { workspace = true } ndarray.workspace = true diff --git a/crates/circuits/sha-macros/tests/flags.rs b/crates/circuits/sha-macros/tests/flags.rs index 9285c9f49d..a370cbd53c 100644 --- a/crates/circuits/sha-macros/tests/flags.rs +++ b/crates/circuits/sha-macros/tests/flags.rs @@ -1,9 +1,9 @@ -use openvm_sha_air::{Sha256Config, ShaConfig}; +use openvm_sha2_air::{Sha256Config, Sha2Config}; use openvm_sha_macros::ColsRef; #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] 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 diff --git a/crates/circuits/sha-macros/tests/nested.rs b/crates/circuits/sha-macros/tests/nested.rs index 6b45fa98bb..d4691f0265 100644 --- a/crates/circuits/sha-macros/tests/nested.rs +++ b/crates/circuits/sha-macros/tests/nested.rs @@ -1,9 +1,9 @@ -use openvm_sha_air::{Sha256Config, ShaConfig}; +use openvm_sha2_air::{Sha256Config, Sha2Config}; use openvm_sha_macros::ColsRef; #[allow(dead_code)] #[derive(ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] struct Test1Cols { pub a: T, pub nested: Test2Cols, @@ -11,7 +11,7 @@ struct Test1Cols { #[allow(dead_code)] #[derive(ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] struct Test2Cols { pub b: T, pub c: [T; WORD_BITS], diff --git a/crates/circuits/sha-macros/tests/simple.rs b/crates/circuits/sha-macros/tests/simple.rs index 39543167f5..1b936720d9 100644 --- a/crates/circuits/sha-macros/tests/simple.rs +++ b/crates/circuits/sha-macros/tests/simple.rs @@ -1,9 +1,9 @@ -use openvm_sha_air::{Sha256Config, ShaConfig}; +use openvm_sha2_air::{Sha256Config, Sha2Config}; use openvm_sha_macros::ColsRef; #[allow(dead_code)] #[derive(ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] struct Test { a: T, b: [T; WORD_BITS], diff --git a/crates/circuits/sha-macros/tests/work-vars.rs b/crates/circuits/sha-macros/tests/work-vars.rs index 47b0547dd2..465e8de9a4 100644 --- a/crates/circuits/sha-macros/tests/work-vars.rs +++ b/crates/circuits/sha-macros/tests/work-vars.rs @@ -1,9 +1,9 @@ -use openvm_sha_air::{Sha256Config, ShaConfig}; +use openvm_sha2_air::{Sha256Config, Sha2Config}; use openvm_sha_macros::ColsRef; #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] pub struct ShaWorkVarsCols< T, const WORD_BITS: usize, diff --git a/crates/circuits/sha-air/Cargo.toml b/crates/circuits/sha2-air/Cargo.toml similarity index 95% rename from crates/circuits/sha-air/Cargo.toml rename to crates/circuits/sha2-air/Cargo.toml index 1b38c15184..531ae34e74 100644 --- a/crates/circuits/sha-air/Cargo.toml +++ b/crates/circuits/sha2-air/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "openvm-sha-air" +name = "openvm-sha2-air" version.workspace = true authors.workspace = true edition.workspace = true diff --git a/crates/circuits/sha-air/src/air.rs b/crates/circuits/sha2-air/src/air.rs similarity index 98% rename from crates/circuits/sha-air/src/air.rs rename to crates/circuits/sha2-air/src/air.rs index 8c8fb4411a..abe1feaff1 100644 --- a/crates/circuits/sha-air/src/air.rs +++ b/crates/circuits/sha2-air/src/air.rs @@ -19,12 +19,12 @@ use super::{ small_sig1_field, }; use crate::{ - constraint_word_addition, word_into_u16_limbs, ShaConfig, ShaDigestColsRef, ShaRoundColsRef, + constraint_word_addition, word_into_u16_limbs, Sha2Config, ShaDigestColsRef, ShaRoundColsRef, }; /// Expects the message to be padded to a multiple of C::BLOCK_WORDS * C::WORD_BITS bits #[derive(Clone, Debug)] -pub struct Sha2Air { +pub struct Sha2Air { pub bitwise_lookup_bus: BitwiseOperationLookupBus, pub row_idx_encoder: Encoder, /// Internal bus for self-interactions in this AIR. @@ -32,7 +32,7 @@ pub struct Sha2Air { _phantom: PhantomData, } -impl Sha2Air { +impl Sha2Air { pub fn new(bitwise_lookup_bus: BitwiseOperationLookupBus, self_bus_idx: BusIndex) -> Self { Self { bitwise_lookup_bus, @@ -43,13 +43,13 @@ impl Sha2Air { } } -impl BaseAir for Sha2Air { +impl BaseAir for Sha2Air { fn width(&self) -> usize { max(C::ROUND_WIDTH, C::DIGEST_WIDTH) } } -impl SubAir for Sha2Air { +impl SubAir for Sha2Air { /// The start column for the sub-air to use type AirContext<'a> = usize @@ -69,7 +69,7 @@ impl SubAir for Sha2Air { } } -impl Sha2Air { +impl Sha2Air { /// 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) { diff --git a/crates/circuits/sha-air/src/columns.rs b/crates/circuits/sha2-air/src/columns.rs similarity index 88% rename from crates/circuits/sha-air/src/columns.rs rename to crates/circuits/sha2-air/src/columns.rs index 784026d70b..829892aaa0 100644 --- a/crates/circuits/sha-air/src/columns.rs +++ b/crates/circuits/sha2-air/src/columns.rs @@ -4,7 +4,7 @@ use openvm_circuit_primitives::utils::not; use openvm_sha_macros::ColsRef; use openvm_stark_backend::p3_field::FieldAlgebra; -use crate::ShaConfig; +use crate::Sha2Config; /// In each SHA block: /// - First C::ROUND_ROWS rows use ShaRoundCols @@ -20,7 +20,7 @@ use crate::ShaConfig; /// 2. Specific constraints to use the appropriate struct, with flags helping to do conditional constraints #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] pub struct ShaRoundCols< T, const WORD_BITS: usize, @@ -30,16 +30,16 @@ pub struct ShaRoundCols< const ROUNDS_PER_ROW_MINUS_ONE: usize, const ROW_VAR_CNT: usize, > { - pub flags: ShaFlagsCols, + pub flags: Sha2FlagsCols, pub work_vars: ShaWorkVarsCols, pub schedule_helper: - ShaMessageHelperCols, + Sha2MessageHelperCols, pub message_schedule: ShaMessageScheduleCols, } #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] pub struct ShaDigestCols< T, const WORD_BITS: usize, @@ -50,11 +50,11 @@ pub struct ShaDigestCols< const ROUNDS_PER_ROW_MINUS_ONE: usize, const ROW_VAR_CNT: usize, > { - pub flags: ShaFlagsCols, + pub flags: Sha2FlagsCols, /// Will serve as previous hash values for the next block pub hash: ShaWorkVarsCols, pub schedule_helper: - ShaMessageHelperCols, + Sha2MessageHelperCols, /// 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; WORD_U8S]; HASH_WORDS], @@ -65,7 +65,7 @@ pub struct ShaDigestCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] pub struct ShaMessageScheduleCols< T, const WORD_BITS: usize, @@ -81,7 +81,7 @@ pub struct ShaMessageScheduleCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] +#[config(Sha2Config)] pub struct ShaWorkVarsCols< T, const WORD_BITS: usize, @@ -100,8 +100,8 @@ pub struct ShaWorkVarsCols< /// Note: these need to be correctly assigned for every row even on padding rows #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] -pub struct ShaMessageHelperCols< +#[config(Sha2Config)] +pub struct Sha2MessageHelperCols< T, const WORD_U16S: usize, const ROUNDS_PER_ROW: usize, @@ -119,8 +119,8 @@ pub struct ShaMessageHelperCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] -#[config(ShaConfig)] -pub struct ShaFlagsCols { +#[config(Sha2Config)] +pub struct Sha2FlagsCols { pub is_round_row: T, /// A flag that indicates if the current row is among the first 4 rows of a block (the message rows) pub is_first_4_rows: T, @@ -135,7 +135,7 @@ pub struct ShaFlagsCols { } impl, const ROW_VAR_CNT: usize> - ShaFlagsCols + Sha2FlagsCols { pub fn is_not_padding_row(&self) -> O { self.is_round_row + self.is_digest_row @@ -149,7 +149,7 @@ impl, const ROW_VAR_CNT: usize> } } -impl> ShaFlagsColsRef<'_, T> { +impl> Sha2FlagsColsRef<'_, T> { pub fn is_not_padding_row(&self) -> O { *self.is_round_row + *self.is_digest_row } diff --git a/crates/circuits/sha-air/src/config.rs b/crates/circuits/sha2-air/src/config.rs similarity index 98% rename from crates/circuits/sha-air/src/config.rs rename to crates/circuits/sha2-air/src/config.rs index 3fdbb24f40..c0f9964039 100644 --- a/crates/circuits/sha-air/src/config.rs +++ b/crates/circuits/sha2-air/src/config.rs @@ -2,7 +2,7 @@ use std::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use crate::{ShaDigestColsRef, ShaRoundColsRef}; -pub trait ShaConfig: Send + Sync + Clone { +pub trait Sha2Config: Send + Sync + Clone { type Word: 'static + Shr + Shl @@ -72,7 +72,7 @@ pub trait ShaConfig: Send + Sync + Clone { #[derive(Clone)] pub struct Sha256Config; -impl ShaConfig for Sha256Config { +impl Sha2Config for Sha256Config { // ==== Do not change these constants! ==== type Word = u32; /// Number of bits in a SHA256 word @@ -136,7 +136,7 @@ pub const SHA256_H: [u32; 8] = [ #[derive(Clone)] pub struct Sha512Config; -impl ShaConfig for Sha512Config { +impl Sha2Config for Sha512Config { // ==== Do not change these constants! ==== type Word = u64; /// Number of bits in a SHA512 word @@ -282,7 +282,7 @@ pub const SHA512_H: [u64; 8] = [ #[derive(Clone)] pub struct Sha384Config; -impl ShaConfig for Sha384Config { +impl Sha2Config for Sha384Config { // ==== Do not change these constants! ==== type Word = u64; /// Number of bits in a SHA384 word diff --git a/crates/circuits/sha-air/src/lib.rs b/crates/circuits/sha2-air/src/lib.rs similarity index 100% rename from crates/circuits/sha-air/src/lib.rs rename to crates/circuits/sha2-air/src/lib.rs diff --git a/crates/circuits/sha-air/src/tests.rs b/crates/circuits/sha2-air/src/tests.rs similarity index 90% rename from crates/circuits/sha-air/src/tests.rs rename to crates/circuits/sha2-air/src/tests.rs index 8832a976e3..58aeda0b7c 100644 --- a/crates/circuits/sha-air/src/tests.rs +++ b/crates/circuits/sha2-air/src/tests.rs @@ -22,38 +22,38 @@ use openvm_stark_sdk::utils::create_seeded_rng; use rand::Rng; use crate::{ - compose, small_sig0_field, Sha256Config, Sha2Air, Sha384Config, Sha512Config, ShaConfig, + compose, small_sig0_field, Sha256Config, Sha2Air, Sha2Config, Sha384Config, Sha512Config, ShaDigestColsRefMut, ShaRoundColsRef, ShaRoundColsRefMut, }; // A wrapper AIR purely for testing purposes #[derive(Clone, Debug)] -pub struct ShaTestAir { +pub struct ShaTestAir { pub sub_air: Sha2Air, } -impl BaseAirWithPublicValues for ShaTestAir {} -impl PartitionedBaseAir for ShaTestAir {} -impl BaseAir for ShaTestAir { +impl BaseAirWithPublicValues for ShaTestAir {} +impl PartitionedBaseAir for ShaTestAir {} +impl BaseAir for ShaTestAir { fn width(&self) -> usize { as BaseAir>::width(&self.sub_air) } } -impl Air for ShaTestAir { +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 ShaTestChip { +pub struct ShaTestChip { pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, pub records: Vec<(Vec, bool)>, // length of inner vec is BLOCK_U8S } -impl Chip for ShaTestChip +impl Chip for ShaTestChip where Val: PrimeField32, { @@ -71,7 +71,7 @@ where } } -impl ChipUsageGetter for ShaTestChip { +impl ChipUsageGetter for ShaTestChip { fn air_name(&self) -> String { get_air_name(&self.air) } @@ -85,7 +85,7 @@ impl ChipUsageGetter for ShaTestChip { } const SELF_BUS_IDX: BusIndex = 28; -fn rand_sha_test() { +fn rand_sha_test() { let mut rng = create_seeded_rng(); let tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); @@ -130,13 +130,13 @@ fn rand_sha384_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 { +pub struct ShaTestBadFinalHashChip { pub air: ShaTestAir, pub bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, pub records: Vec<(Vec, bool)>, // length of inner vec should be C::BLOCK_U8S } -impl Chip for ShaTestBadFinalHashChip +impl Chip for ShaTestBadFinalHashChip where Val: PrimeField32, { @@ -197,7 +197,7 @@ where // Copy of private method in Sha256Air used for testing /// Puts the correct intermed_4 in the `next_row` -fn generate_intermed_4( +fn generate_intermed_4( local_cols: &ShaRoundColsRef, next_cols: &mut ShaRoundColsRefMut, ) { @@ -237,7 +237,7 @@ fn generate_intermed_4( } } -impl ChipUsageGetter for ShaTestBadFinalHashChip { +impl ChipUsageGetter for ShaTestBadFinalHashChip { fn air_name(&self) -> String { get_air_name(&self.air) } @@ -250,7 +250,7 @@ impl ChipUsageGetter for ShaTestBadFinalHashChip { } } -fn test_sha_final_hash_constraints() { +fn test_sha_final_hash_constraints() { let mut rng = create_seeded_rng(); let tester = VmChipTestBuilder::default(); let bitwise_bus = BitwiseOperationLookupBus::new(BITWISE_OP_LOOKUP_BUS); diff --git a/crates/circuits/sha-air/src/trace.rs b/crates/circuits/sha2-air/src/trace.rs similarity index 99% rename from crates/circuits/sha-air/src/trace.rs rename to crates/circuits/sha2-air/src/trace.rs index e21795179c..ed302edefd 100644 --- a/crates/circuits/sha-air/src/trace.rs +++ b/crates/circuits/sha2-air/src/trace.rs @@ -15,14 +15,14 @@ use super::{ }; use crate::{ 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, ShaRoundColsRef, + word_into_u16_limbs, word_into_u8_limbs, Sha2Config, ShaDigestColsRefMut, ShaRoundColsRef, WrappingAdd, }; /// 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 Sha2Air { +impl Sha2Air { /// 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: &[C::Word], input: Vec) -> Vec { @@ -747,7 +747,7 @@ impl Sha2Air { } /// `records` consists of pairs of `(input_block, is_last_block)`. -pub fn generate_trace( +pub fn generate_trace( sub_air: &Sha2Air, bitwise_lookup_chip: SharedBitwiseOperationLookupChip<8>, records: Vec<(Vec, bool)>, @@ -761,7 +761,7 @@ pub fn generate_trace( let width = as BaseAir>::width(sub_air); let mut values = F::zero_vec(height * width); - struct BlockContext { + struct BlockContext { prev_hash: Vec, // len is C::HASH_WORDS local_block_idx: u32, global_block_idx: u32, diff --git a/crates/circuits/sha-air/src/utils.rs b/crates/circuits/sha2-air/src/utils.rs similarity index 87% rename from crates/circuits/sha-air/src/utils.rs rename to crates/circuits/sha2-air/src/utils.rs index 417e741c09..c8e8b8d6c1 100644 --- a/crates/circuits/sha-air/src/utils.rs +++ b/crates/circuits/sha2-air/src/utils.rs @@ -6,25 +6,25 @@ use openvm_circuit_primitives::{ use openvm_stark_backend::{p3_air::AirBuilder, p3_field::FieldAlgebra}; use rand::{rngs::StdRng, Rng}; -use crate::{RotateRight, ShaConfig}; +use crate::{RotateRight, Sha2Config}; /// Convert a word into a list of 8-bit limbs in little endian -pub fn word_into_u8_limbs(num: impl Into) -> Vec { +pub fn word_into_u8_limbs(num: impl Into) -> Vec { word_into_limbs::(num.into(), C::WORD_U8S) } /// Convert a word into a list of 16-bit limbs in little endian -pub fn word_into_u16_limbs(num: impl Into) -> Vec { +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 { +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 { +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| { @@ -37,7 +37,7 @@ pub fn word_into_limbs(num: C::Word, num_limbs: usize) -> Vec } /// Convert a u32 into a list of 1-bit limbs in little endian -pub fn u32_into_bits(num: u32) -> Vec { +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)) @@ -45,7 +45,7 @@ pub fn u32_into_bits(num: u32) -> Vec { } /// Convert a list of limbs in little endian into a Word -pub fn limbs_into_word(limbs: &[u32]) -> C::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() @@ -111,7 +111,7 @@ pub(crate) fn xor( /// Choose function from the SHA spec #[inline] -pub fn ch(x: C::Word, y: C::Word, z: C::Word) -> C::Word { +pub fn ch(x: C::Word, y: C::Word, z: C::Word) -> C::Word { (x & y) ^ ((!x) & z) } @@ -128,7 +128,7 @@ pub(crate) fn ch_field( } /// Majority function from the SHA spec -pub fn maj(x: C::Word, y: C::Word, z: C::Word) -> C::Word { +pub fn maj(x: C::Word, y: C::Word, z: C::Word) -> C::Word { (x & y) ^ (x & z) ^ (y & z) } @@ -153,7 +153,7 @@ pub(crate) fn maj_field( } /// Big sigma_0 function from the SHA spec -pub fn big_sig0(x: C::Word) -> C::Word { +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) } else { @@ -163,7 +163,7 @@ pub fn big_sig0(x: C::Word) -> C::Word { /// Computes BigSigma0(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn big_sig0_field( +pub(crate) fn big_sig0_field( x: &[impl Into + Clone], ) -> Vec { if C::WORD_BITS == 32 { @@ -174,7 +174,7 @@ pub(crate) fn big_sig0_field( } /// Big sigma_1 function from the SHA spec -pub fn big_sig1(x: C::Word) -> C::Word { +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) } else { @@ -184,7 +184,7 @@ pub fn big_sig1(x: C::Word) -> C::Word { /// Computes BigSigma1(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn big_sig1_field( +pub(crate) fn big_sig1_field( x: &[impl Into + Clone], ) -> Vec { if C::WORD_BITS == 32 { @@ -195,7 +195,7 @@ pub(crate) fn big_sig1_field( } /// Small sigma_0 function from the SHA spec -pub fn small_sig0(x: C::Word) -> C::Word { +pub fn small_sig0(x: C::Word) -> C::Word { if C::WORD_BITS == 32 { x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) } else { @@ -205,7 +205,7 @@ pub fn small_sig0(x: C::Word) -> C::Word { /// Computes SmallSigma0(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn small_sig0_field( +pub(crate) fn small_sig0_field( x: &[impl Into + Clone], ) -> Vec { if C::WORD_BITS == 32 { @@ -216,7 +216,7 @@ pub(crate) fn small_sig0_field( } /// Small sigma_1 function from the SHA spec -pub fn small_sig1(x: C::Word) -> C::Word { +pub fn small_sig1(x: C::Word) -> C::Word { if C::WORD_BITS == 32 { x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) } else { @@ -226,7 +226,7 @@ pub fn small_sig1(x: C::Word) -> C::Word { /// Computes SmallSigma1(x), where x is a [C::WORD_BITS] bit number in little-endian #[inline] -pub(crate) fn small_sig1_field( +pub(crate) fn small_sig1_field( x: &[impl Into + Clone], ) -> Vec { if C::WORD_BITS == 32 { @@ -251,7 +251,7 @@ pub fn get_flag_pt_array(encoder: &Encoder, flag_idx: usize) -> Vec { /// 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( +pub fn constraint_word_addition( builder: &mut AB, terms_bits: &[&[impl Into + Clone]], terms_limb: &[&[impl Into + Clone]], diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml index f3ca81462d..b64fa04318 100644 --- a/crates/sdk/Cargo.toml +++ b/crates/sdk/Cargo.toml @@ -18,8 +18,8 @@ openvm-ecc-circuit = { workspace = true } openvm-ecc-transpiler = { workspace = true } openvm-keccak256-circuit = { workspace = true } openvm-keccak256-transpiler = { workspace = true } -openvm-sha256-circuit = { workspace = true } -openvm-sha256-transpiler = { workspace = true } +openvm-sha2-circuit = { workspace = true } +openvm-sha2-transpiler = { workspace = true } openvm-pairing-circuit = { workspace = true } openvm-pairing-transpiler = { workspace = true } openvm-native-circuit = { workspace = true } diff --git a/crates/sdk/src/config/global.rs b/crates/sdk/src/config/global.rs index 92cba17d6a..754838b441 100644 --- a/crates/sdk/src/config/global.rs +++ b/crates/sdk/src/config/global.rs @@ -35,8 +35,8 @@ use openvm_rv32im_circuit::{ use openvm_rv32im_transpiler::{ Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension, }; -use openvm_sha256_circuit::{Sha2, Sha2Executor, Sha2Periphery}; -use openvm_sha256_transpiler::Sha2TranspilerExtension; +use openvm_sha2_circuit::{Sha2, Sha2Executor, Sha2Periphery}; +use openvm_sha2_transpiler::Sha2TranspilerExtension; use openvm_stark_backend::p3_field::PrimeField32; use openvm_transpiler::transpiler::Transpiler; use serde::{Deserialize, Serialize}; @@ -51,7 +51,7 @@ pub struct SdkVmConfig { pub rv32i: Option, pub io: Option, pub keccak: Option, - pub sha256: Option, + pub sha2: Option, pub native: Option, pub castf: Option, @@ -135,7 +135,7 @@ impl SdkVmConfig { if self.keccak.is_some() { transpiler = transpiler.with_extension(Keccak256TranspilerExtension); } - if self.sha256.is_some() { + if self.sha2.is_some() { transpiler = transpiler.with_extension(Sha2TranspilerExtension); } if self.rv32m.is_some() { @@ -186,7 +186,7 @@ impl VmConfig for SdkVmConfig { if self.keccak.is_some() { complex = complex.extend(&Keccak256)?; } - if self.sha256.is_some() { + if self.sha2.is_some() { complex = complex.extend(&Sha2)?; } if self.native.is_some() { diff --git a/docs/specs/circuit.md b/docs/specs/circuit.md index 4238c7c27b..bd34344674 100644 --- a/docs/specs/circuit.md +++ b/docs/specs/circuit.md @@ -104,7 +104,7 @@ The chips that fall into these categories are: | FriReducedOpeningChip | – | – | Case 1. | | NativePoseidon2Chip | – | – | Case 1. | | Rv32HintStoreChip | – | – | Case 1. | -| Sha256VmChip | – | – | Case 1. | +| Sha2VmChip | – | – | Case 1. | The PhantomChip satisfies the condition because `1 < 3`. diff --git a/docs/specs/isa-table.md b/docs/specs/isa-table.md index 75cf1bad2c..a96b59e6bb 100644 --- a/docs/specs/isa-table.md +++ b/docs/specs/isa-table.md @@ -134,7 +134,9 @@ In the tables below, we provide the mapping between the `LocalOpcode` and `Phant | VM Extension | `LocalOpcode` | ISA Instruction | | ------------- | ---------- | ------------- | -| SHA2-256 | `Rv32Sha256Opcode::SHA256` | SHA256_RV32 | +| SHA2-256 | `Rv32Sha2Opcode::SHA256` | SHA256_RV32 | +| SHA2-512 | `Rv32Sha2Opcode::SHA512` | SHA512_RV32 | +| SHA2-384 | `Rv32Sha2Opcode::SHA384` | SHA384_RV32 | ## BigInt Extension diff --git a/examples/sha2/Cargo.toml b/examples/sha2/Cargo.toml new file mode 100644 index 0000000000..df7e72bac5 --- /dev/null +++ b/examples/sha2/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sha2-example" +version = "0.0.0" +edition = "2021" + +[workspace] +members = [] + +[dependencies] +# TODO: update rev after PR is merged +openvm = { git = "https://github.com/openvm-org/openvm.git", features = [ + "std", +], rev = "5180cea6342f43ac6523e0057e73e0dc9ecece3a"} +# TODO: update rev after PR is merged +openvm-sha2-guest = { git = "https://github.com/openvm-org/openvm.git", rev = "5180cea6342f43ac6523e0057e73e0dc9ecece3a" } +hex = { version = "0.4.3" } + +[features] +default = [] diff --git a/examples/sha256/openvm.toml b/examples/sha2/openvm.toml similarity index 100% rename from examples/sha256/openvm.toml rename to examples/sha2/openvm.toml diff --git a/examples/sha2/src/main.rs b/examples/sha2/src/main.rs new file mode 100644 index 0000000000..44bcd119b4 --- /dev/null +++ b/examples/sha2/src/main.rs @@ -0,0 +1,39 @@ +// ANCHOR: imports +use core::hint::black_box; + +use hex::FromHex; +use openvm_sha2_guest::{sha256, sha384, sha512}; +// ANCHOR_END: imports + +// ANCHOR: main +openvm::entry!(main); + +pub fn main() { + let test_vectors = [( + "", + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", + )]; + for (input, expected_output_sha256, expected_output_sha512, expected_output_sha384) in + test_vectors.iter() + { + let input = Vec::from_hex(input).unwrap(); + let expected_output_sha256 = Vec::from_hex(expected_output_sha256).unwrap(); + let expected_output_sha512 = Vec::from_hex(expected_output_sha512).unwrap(); + let expected_output_sha384 = Vec::from_hex(expected_output_sha384).unwrap(); + let output = sha256(black_box(&input)); + if output != *expected_output_sha256 { + panic!(); + } + let output = sha512(black_box(&input)); + if output != *expected_output_sha512 { + panic!(); + } + let output = sha384(black_box(&input)); + if output != *expected_output_sha384 { + panic!(); + } + } +} +// ANCHOR_END: main diff --git a/examples/sha256/Cargo.toml b/examples/sha256/Cargo.toml deleted file mode 100644 index 48d6887c5c..0000000000 --- a/examples/sha256/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "sha256-example" -version = "0.0.0" -edition = "2021" - -[workspace] -members = [] - -[dependencies] -openvm = { git = "https://github.com/openvm-org/openvm.git", features = [ - "std", -], branch = "develop" } -openvm-sha256-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop" } -hex = { version = "0.4.3" } - -[features] -default = [] diff --git a/examples/sha256/src/main.rs b/examples/sha256/src/main.rs deleted file mode 100644 index 502a12366b..0000000000 --- a/examples/sha256/src/main.rs +++ /dev/null @@ -1,25 +0,0 @@ -// ANCHOR: imports -use core::hint::black_box; - -use hex::FromHex; -use openvm_sha256_guest::sha256; -// ANCHOR_END: imports - -// ANCHOR: main -openvm::entry!(main); - -pub fn main() { - let test_vectors = [( - "", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - )]; - for (input, expected_output) in test_vectors.iter() { - let input = Vec::from_hex(input).unwrap(); - let expected_output = Vec::from_hex(expected_output).unwrap(); - let output = sha256(&black_box(input)); - if output != *expected_output { - panic!(); - } - } -} -// ANCHOR_END: main diff --git a/extensions/sha256/circuit/Cargo.toml b/extensions/sha2/circuit/Cargo.toml similarity index 88% rename from extensions/sha256/circuit/Cargo.toml rename to extensions/sha2/circuit/Cargo.toml index 7425f12842..48301332b0 100644 --- a/extensions/sha256/circuit/Cargo.toml +++ b/extensions/sha2/circuit/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "openvm-sha256-circuit" +name = "openvm-sha2-circuit" version.workspace = true authors.workspace = true edition.workspace = true -description = "OpenVM circuit extension for sha256" +description = "OpenVM circuit extension for SHA-2" [dependencies] openvm-stark-backend = { workspace = true } @@ -13,9 +13,9 @@ openvm-circuit-primitives-derive = { workspace = true } openvm-circuit-derive = { workspace = true } openvm-circuit = { workspace = true } openvm-instructions = { workspace = true } -openvm-sha256-transpiler = { workspace = true } +openvm-sha2-transpiler = { workspace = true } openvm-rv32im-circuit = { workspace = true } -openvm-sha-air = { workspace = true } +openvm-sha2-air = { workspace = true } openvm-sha-macros = { workspace = true } derive-new.workspace = true diff --git a/extensions/sha256/circuit/README.md b/extensions/sha2/circuit/README.md similarity index 98% rename from extensions/sha256/circuit/README.md rename to extensions/sha2/circuit/README.md index 1e794cd35c..189c0675b8 100644 --- a/extensions/sha256/circuit/README.md +++ b/extensions/sha2/circuit/README.md @@ -1,6 +1,6 @@ -# SHA256 VM Extension +# SHA-2 VM Extension -This crate contains the circuit for the SHA256 VM extension. +This crate contains the circuit for the SHA-2 VM extension. ## SHA-256 Algorithm Summary diff --git a/extensions/sha256/circuit/src/extension.rs b/extensions/sha2/circuit/src/extension.rs similarity index 97% rename from extensions/sha256/circuit/src/extension.rs rename to extensions/sha2/circuit/src/extension.rs index 55954693b2..e67ce2be1a 100644 --- a/extensions/sha256/circuit/src/extension.rs +++ b/extensions/sha2/circuit/src/extension.rs @@ -13,8 +13,8 @@ use openvm_rv32im_circuit::{ Rv32I, Rv32IExecutor, Rv32IPeriphery, Rv32Io, Rv32IoExecutor, Rv32IoPeriphery, Rv32M, Rv32MExecutor, Rv32MPeriphery, }; -use openvm_sha256_transpiler::Rv32Sha2Opcode; -use openvm_sha_air::{Sha256Config, Sha384Config, Sha512Config}; +use openvm_sha2_air::{Sha256Config, Sha384Config, Sha512Config}; +use openvm_sha2_transpiler::Rv32Sha2Opcode; use openvm_stark_backend::p3_field::PrimeField32; use serde::{Deserialize, Serialize}; diff --git a/extensions/sha2/circuit/src/lib.rs b/extensions/sha2/circuit/src/lib.rs new file mode 100644 index 0000000000..cc51aaaf20 --- /dev/null +++ b/extensions/sha2/circuit/src/lib.rs @@ -0,0 +1,5 @@ +mod sha2_chip; +pub use sha2_chip::*; + +mod extension; +pub use extension::*; diff --git a/extensions/sha256/circuit/src/sha256_chip/air.rs b/extensions/sha2/circuit/src/sha2_chip/air.rs similarity index 96% rename from extensions/sha256/circuit/src/sha256_chip/air.rs rename to extensions/sha2/circuit/src/sha2_chip/air.rs index e48991d5ac..18cd0ebd1e 100644 --- a/extensions/sha256/circuit/src/sha256_chip/air.rs +++ b/extensions/sha2/circuit/src/sha2_chip/air.rs @@ -14,7 +14,7 @@ use openvm_instructions::{ riscv::{RV32_CELL_BITS, RV32_MEMORY_AS, RV32_REGISTER_AS, RV32_REGISTER_NUM_LIMBS}, LocalOpcode, }; -use openvm_sha_air::{compose, Sha256Config, Sha2Air, Sha512Config}; +use openvm_sha2_air::{compose, Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{ interaction::InteractionBuilder, p3_air::{Air, AirBuilder, BaseAir}, @@ -23,10 +23,10 @@ use openvm_stark_backend::{ rap::{BaseAirWithPublicValues, PartitionedBaseAir}, }; -use super::{Sha2Variant, ShaChipConfig, ShaVmDigestColsRef, ShaVmRoundColsRef}; +use super::{Sha2Variant, Sha2VmDigestColsRef, Sha2VmRoundColsRef, ShaChipConfig}; -/// Sha256VmAir does all constraints related to message padding and -/// the Sha256Air subair constrains the actual hash +/// Sha2VmAir does all constraints related to message padding and +/// the Sha2Air subair constrains the actual hash #[derive(Clone, Debug, derive_new::new)] pub struct Sha2VmAir { pub execution_bridge: ExecutionBridge, @@ -137,8 +137,8 @@ impl Sha2VmAir { fn eval_padding(&self, builder: &mut AB) { let main = builder.main(); let (local, next) = (main.row_slice(0), main.row_slice(1)); - let local_cols = ShaVmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); - let next_cols = ShaVmRoundColsRef::::from::(&next[..C::VM_ROUND_WIDTH]); + let local_cols = Sha2VmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); + let next_cols = Sha2VmRoundColsRef::::from::(&next[..C::VM_ROUND_WIDTH]); // Constrain the sanity of the padding flags self.padding_encoder @@ -156,8 +156,8 @@ impl Sha2VmAir { fn eval_padding_transitions( &self, builder: &mut AB, - local: &ShaVmRoundColsRef, - next: &ShaVmRoundColsRef, + local: &Sha2VmRoundColsRef, + next: &Sha2VmRoundColsRef, ) { let next_is_last_row = *next.inner.flags.is_digest_row * *next.inner.flags.is_last_block; @@ -295,7 +295,7 @@ impl Sha2VmAir { fn eval_padding_row( &self, builder: &mut AB, - local: &ShaVmRoundColsRef, + local: &Sha2VmRoundColsRef, ) { let message = (0..C::READ_SIZE) .map(|i| { @@ -446,8 +446,8 @@ impl Sha2VmAir { fn eval_transitions(&self, builder: &mut AB) { let main = builder.main(); let (local, next) = (main.row_slice(0), main.row_slice(1)); - let local_cols = ShaVmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); - let next_cols = ShaVmRoundColsRef::::from::(&next[..C::VM_ROUND_WIDTH]); + let local_cols = Sha2VmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); + let next_cols = Sha2VmRoundColsRef::::from::(&next[..C::VM_ROUND_WIDTH]); let is_last_row = *local_cols.inner.flags.is_last_block * *local_cols.inner.flags.is_digest_row; @@ -483,7 +483,7 @@ impl Sha2VmAir { fn eval_reads(&self, builder: &mut AB) { let main = builder.main(); let local = main.row_slice(0); - let local_cols = ShaVmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); + let local_cols = Sha2VmRoundColsRef::::from::(&local[..C::VM_ROUND_WIDTH]); let message: Vec = (0..C::READ_SIZE) .map(|i| { @@ -534,7 +534,7 @@ impl Sha2VmAir { fn eval_last_row(&self, builder: &mut AB) { let main = builder.main(); let local = main.row_slice(0); - let local_cols = ShaVmDigestColsRef::::from::(&local[..C::VM_DIGEST_WIDTH]); + let local_cols = Sha2VmDigestColsRef::::from::(&local[..C::VM_DIGEST_WIDTH]); let timestamp: AB::Var = local_cols.from_state.timestamp; let mut timestamp_delta: usize = 0; diff --git a/extensions/sha256/circuit/src/sha256_chip/columns.rs b/extensions/sha2/circuit/src/sha2_chip/columns.rs similarity index 94% rename from extensions/sha256/circuit/src/sha256_chip/columns.rs rename to extensions/sha2/circuit/src/sha2_chip/columns.rs index ecd56b63db..1f1410a119 100644 --- a/extensions/sha256/circuit/src/sha256_chip/columns.rs +++ b/extensions/sha2/circuit/src/sha2_chip/columns.rs @@ -5,7 +5,7 @@ use openvm_circuit::{ system::memory::offline_checker::{MemoryBaseAuxCols, MemoryReadAuxCols}, }; use openvm_instructions::riscv::RV32_REGISTER_NUM_LIMBS; -use openvm_sha_air::{ +use openvm_sha2_air::{ ShaDigestCols, ShaDigestColsRef, ShaDigestColsRefMut, ShaRoundCols, ShaRoundColsRef, ShaRoundColsRefMut, }; @@ -18,7 +18,7 @@ use crate::ShaChipConfig; #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] #[config(ShaChipConfig)] -pub struct ShaVmRoundCols< +pub struct Sha2VmRoundCols< T, const WORD_BITS: usize, const WORD_U8S: usize, @@ -27,7 +27,7 @@ pub struct ShaVmRoundCols< const ROUNDS_PER_ROW_MINUS_ONE: usize, const ROW_VAR_CNT: usize, > { - pub control: ShaVmControlCols, + pub control: Sha2VmControlCols, pub inner: ShaRoundCols< T, WORD_BITS, @@ -44,7 +44,7 @@ pub struct ShaVmRoundCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] #[config(ShaChipConfig)] -pub struct ShaVmDigestCols< +pub struct Sha2VmDigestCols< T, const WORD_BITS: usize, const WORD_U8S: usize, @@ -56,7 +56,7 @@ pub struct ShaVmDigestCols< const NUM_WRITES: usize, const WRITE_SIZE: usize, > { - pub control: ShaVmControlCols, + pub control: Sha2VmControlCols, pub inner: ShaDigestCols< T, WORD_BITS, @@ -88,7 +88,7 @@ pub struct ShaVmDigestCols< #[repr(C)] #[derive(Clone, Copy, Debug, ColsRef)] #[config(ShaChipConfig)] -pub struct ShaVmControlCols { +pub struct Sha2VmControlCols { /// Note: We will use the buffer in `inner.message_schedule` as the message data /// This is the length of the entire message in bytes pub len: T, diff --git a/extensions/sha256/circuit/src/sha256_chip/config.rs b/extensions/sha2/circuit/src/sha2_chip/config.rs similarity index 87% rename from extensions/sha256/circuit/src/sha256_chip/config.rs rename to extensions/sha2/circuit/src/sha2_chip/config.rs index bddb29a5f3..86bd14bcf3 100644 --- a/extensions/sha256/circuit/src/sha256_chip/config.rs +++ b/extensions/sha2/circuit/src/sha2_chip/config.rs @@ -1,8 +1,8 @@ use openvm_instructions::riscv::RV32_CELL_BITS; -use openvm_sha256_transpiler::Rv32Sha2Opcode; -use openvm_sha_air::{Sha256Config, Sha384Config, Sha512Config, ShaConfig}; +use openvm_sha2_air::{Sha256Config, Sha2Config, Sha384Config, Sha512Config}; +use openvm_sha2_transpiler::Rv32Sha2Opcode; -use super::{ShaVmControlColsRef, ShaVmDigestColsRef, ShaVmRoundColsRef}; +use super::{Sha2VmControlColsRef, Sha2VmDigestColsRef, Sha2VmRoundColsRef}; pub enum Sha2Variant { Sha256, @@ -10,17 +10,17 @@ pub enum Sha2Variant { Sha384, } -pub trait ShaChipConfig: ShaConfig { +pub trait ShaChipConfig: Sha2Config { // Differentiate between the two SHA256 variants const VARIANT: Sha2Variant; // Name of the opcode const OPCODE_NAME: &'static str; /// Width of the ShaVmControlCols - const VM_CONTROL_WIDTH: usize = ShaVmControlColsRef::::width::(); + const VM_CONTROL_WIDTH: usize = Sha2VmControlColsRef::::width::(); /// Width of the ShaVmRoundCols - const VM_ROUND_WIDTH: usize = ShaVmRoundColsRef::::width::(); + const VM_ROUND_WIDTH: usize = Sha2VmRoundColsRef::::width::(); /// Width of the ShaVmDigestCols - const VM_DIGEST_WIDTH: usize = ShaVmDigestColsRef::::width::(); + const VM_DIGEST_WIDTH: usize = Sha2VmDigestColsRef::::width::(); /// Width of the ShaVmCols const VM_WIDTH: usize = if Self::VM_ROUND_WIDTH > Self::VM_DIGEST_WIDTH { Self::VM_ROUND_WIDTH diff --git a/extensions/sha256/circuit/src/sha256_chip/mod.rs b/extensions/sha2/circuit/src/sha2_chip/mod.rs similarity index 99% rename from extensions/sha256/circuit/src/sha256_chip/mod.rs rename to extensions/sha2/circuit/src/sha2_chip/mod.rs index 3fcd181edf..00c132e41e 100644 --- a/extensions/sha256/circuit/src/sha256_chip/mod.rs +++ b/extensions/sha2/circuit/src/sha2_chip/mod.rs @@ -17,7 +17,7 @@ use openvm_instructions::{ riscv::{RV32_MEMORY_AS, RV32_REGISTER_AS}, }; use openvm_rv32im_circuit::adapters::read_rv32_register; -use openvm_sha_air::{Sha256Config, Sha2Air, Sha512Config}; +use openvm_sha2_air::{Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{interaction::BusIndex, p3_field::PrimeField32}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256, Sha384, Sha512}; @@ -51,7 +51,7 @@ pub struct Sha2Record { pub len_read: RecordId, pub input_records: Vec>, // type is like Vec<[RecordId; C::NUM_READ_ROWS]> pub input_message: Vec>>, // type is like Vec<[[u8; C::SHA256_READ_SIZE]; C::SHA256_NUM_READ_ROWS]> - pub digest_writes: Vec, // one write for sha256, two for sha512 + pub digest_writes: Vec, // one write for sha256, two for sha512 and sha384 } impl Sha2VmChip { diff --git a/extensions/sha256/circuit/src/sha256_chip/tests.rs b/extensions/sha2/circuit/src/sha2_chip/tests.rs similarity index 94% rename from extensions/sha256/circuit/src/sha256_chip/tests.rs rename to extensions/sha2/circuit/src/sha2_chip/tests.rs index 92bbcb8185..9279e7d019 100644 --- a/extensions/sha256/circuit/src/sha256_chip/tests.rs +++ b/extensions/sha2/circuit/src/sha2_chip/tests.rs @@ -6,14 +6,14 @@ use openvm_circuit_primitives::bitwise_op_lookup::{ BitwiseOperationLookupBus, SharedBitwiseOperationLookupChip, }; use openvm_instructions::{instruction::Instruction, riscv::RV32_CELL_BITS, LocalOpcode}; -use openvm_sha256_transpiler::Rv32Sha2Opcode::{self, *}; -use openvm_sha_air::{get_random_message, Sha256Config, Sha384Config, Sha512Config}; +use openvm_sha2_air::{get_random_message, Sha256Config, Sha384Config, Sha512Config}; +use openvm_sha2_transpiler::Rv32Sha2Opcode::{self, *}; 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}; use super::{Sha2VmChip, ShaChipConfig}; -use crate::{sha2_solve, ShaVmDigestColsRef, ShaVmRoundColsRef}; +use crate::{sha2_solve, Sha2VmDigestColsRef, Sha2VmRoundColsRef}; type F = BabyBear; const BUS_IDX: BusIndex = 28; @@ -149,12 +149,12 @@ fn execute_roundtrip_sanity_test(opcode: Rv32Sha2Opcode) { ); println!( - "ShaVmDigestColsRef::::width::(): {}", - ShaVmDigestColsRef::::width::() + "Sha2VmDigestColsRef::::width::(): {}", + Sha2VmDigestColsRef::::width::() ); println!( - "ShaVmRoundColsRef::::width::(): {}", - ShaVmRoundColsRef::::width::() + "Sha2VmRoundColsRef::::width::(): {}", + Sha2VmRoundColsRef::::width::() ); let num_tests: usize = 1; diff --git a/extensions/sha256/circuit/src/sha256_chip/trace.rs b/extensions/sha2/circuit/src/sha2_chip/trace.rs similarity index 97% rename from extensions/sha256/circuit/src/sha256_chip/trace.rs rename to extensions/sha2/circuit/src/sha2_chip/trace.rs index 92798ca846..f9364472d5 100644 --- a/extensions/sha256/circuit/src/sha256_chip/trace.rs +++ b/extensions/sha2/circuit/src/sha2_chip/trace.rs @@ -4,7 +4,7 @@ use openvm_circuit::system::memory::offline_checker::MemoryWriteAuxCols; 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_sha_air::{get_flag_pt_array, limbs_into_word, Sha256Config, Sha2Air, Sha512Config}; +use openvm_sha2_air::{get_flag_pt_array, limbs_into_word, Sha256Config, Sha2Air, Sha512Config}; use openvm_stark_backend::{ config::{StarkGenericConfig, Val}, p3_air::BaseAir, @@ -16,8 +16,10 @@ use openvm_stark_backend::{ AirRef, Chip, ChipUsageGetter, }; -use super::{Sha2Variant, Sha2VmChip, ShaChipConfig, ShaVmDigestColsRefMut, ShaVmRoundColsRefMut}; -use crate::sha256_chip::PaddingFlags; +use super::{ + Sha2Variant, Sha2VmChip, Sha2VmDigestColsRefMut, Sha2VmRoundColsRefMut, ShaChipConfig, +}; +use crate::sha2_chip::PaddingFlags; impl Chip for Sha2VmChip, C> where @@ -145,7 +147,7 @@ where for row in 0..C::ROWS_PER_BLOCK { let row_slice = &mut block[row * width..(row + 1) * width]; if row < C::ROUND_ROWS { - let mut cols = ShaVmRoundColsRefMut::from::( + let mut cols = Sha2VmRoundColsRefMut::from::( row_slice[..C::VM_ROUND_WIDTH].borrow_mut(), ); *cols.control.len = Val::::from_canonical_u32(state.message_len); @@ -230,7 +232,7 @@ where if is_last_block { has_padding_occurred = false; } - let mut cols = ShaVmDigestColsRefMut::from::( + let mut cols = Sha2VmDigestColsRefMut::from::( row_slice[..C::VM_DIGEST_WIDTH].borrow_mut(), ); *cols.control.len = Val::::from_canonical_u32(state.message_len); @@ -347,7 +349,7 @@ where // Fill in the invalid rows else { block.par_chunks_mut(width).for_each(|row| { - let cols = ShaVmRoundColsRefMut::from::(row.borrow_mut()); + let cols = Sha2VmRoundColsRefMut::from::(row.borrow_mut()); self.air.sha_subair.generate_default_row(cols.inner); }) } diff --git a/extensions/sha256/circuit/tmp.rs b/extensions/sha2/circuit/tmp.rs similarity index 100% rename from extensions/sha256/circuit/tmp.rs rename to extensions/sha2/circuit/tmp.rs diff --git a/extensions/sha256/guest/Cargo.toml b/extensions/sha2/guest/Cargo.toml similarity index 79% rename from extensions/sha256/guest/Cargo.toml rename to extensions/sha2/guest/Cargo.toml index ee39453272..8dd496539f 100644 --- a/extensions/sha256/guest/Cargo.toml +++ b/extensions/sha2/guest/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "openvm-sha256-guest" +name = "openvm-sha2-guest" version.workspace = true authors.workspace = true edition.workspace = true -description = "Guest extension for Sha256" +description = "Guest extension for SHA-2" [dependencies] openvm-platform = { workspace = true } diff --git a/extensions/sha256/guest/src/lib.rs b/extensions/sha2/guest/src/lib.rs similarity index 100% rename from extensions/sha256/guest/src/lib.rs rename to extensions/sha2/guest/src/lib.rs diff --git a/extensions/sha256/tests/Cargo.toml b/extensions/sha2/tests/Cargo.toml similarity index 74% rename from extensions/sha256/tests/Cargo.toml rename to extensions/sha2/tests/Cargo.toml index 52fb11f9ea..29e68f18b2 100644 --- a/extensions/sha256/tests/Cargo.toml +++ b/extensions/sha2/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "openvm-sha256-integration-tests" -description = "Integration tests for the OpenVM sha256 extension" +name = "openvm-sha2-integration-tests" +description = "Integration tests for the OpenVM SHA-2 extension" version.workspace = true authors.workspace = true edition.workspace = true @@ -12,8 +12,8 @@ openvm-instructions = { workspace = true } openvm-stark-sdk.workspace = true openvm-circuit = { workspace = true, features = ["test-utils"] } openvm-transpiler.workspace = true -openvm-sha256-transpiler.workspace = true -openvm-sha256-circuit.workspace = true +openvm-sha2-transpiler.workspace = true +openvm-sha2-circuit.workspace = true openvm-rv32im-transpiler.workspace = true openvm-toolchain-tests = { path = "../../../crates/toolchain/tests" } eyre.workspace = true diff --git a/extensions/sha256/tests/programs/Cargo.toml b/extensions/sha2/tests/programs/Cargo.toml similarity index 88% rename from extensions/sha256/tests/programs/Cargo.toml rename to extensions/sha2/tests/programs/Cargo.toml index 433ccdc311..c02a00bf82 100644 --- a/extensions/sha256/tests/programs/Cargo.toml +++ b/extensions/sha2/tests/programs/Cargo.toml @@ -1,13 +1,13 @@ [workspace] [package] -name = "openvm-sha256-test-programs" +name = "openvm-sha2-test-programs" version = "0.0.0" edition = "2021" [dependencies] openvm = { path = "../../../../crates/toolchain/openvm" } openvm-platform = { path = "../../../../crates/toolchain/platform" } -openvm-sha256-guest = { path = "../../guest" } +openvm-sha2-guest = { path = "../../guest" } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } serde = { version = "1.0", default-features = false, features = [ "alloc", diff --git a/extensions/sha256/tests/programs/examples/sha.rs b/extensions/sha2/tests/programs/examples/sha.rs similarity index 98% rename from extensions/sha256/tests/programs/examples/sha.rs rename to extensions/sha2/tests/programs/examples/sha.rs index 833649465a..282d0bfa7b 100644 --- a/extensions/sha256/tests/programs/examples/sha.rs +++ b/extensions/sha2/tests/programs/examples/sha.rs @@ -7,7 +7,7 @@ use alloc::vec::Vec; use core::hint::black_box; use hex::FromHex; -use openvm_sha256_guest::{sha256, sha384, sha512}; +use openvm_sha2_guest::{sha256, sha384, sha512}; openvm::entry!(main); diff --git a/extensions/sha256/tests/src/lib.rs b/extensions/sha2/tests/src/lib.rs similarity index 90% rename from extensions/sha256/tests/src/lib.rs rename to extensions/sha2/tests/src/lib.rs index 77ecf1b952..49361b83a9 100644 --- a/extensions/sha256/tests/src/lib.rs +++ b/extensions/sha2/tests/src/lib.rs @@ -6,8 +6,8 @@ mod tests { use openvm_rv32im_transpiler::{ Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension, }; - use openvm_sha256_circuit::Sha2Rv32Config; - use openvm_sha256_transpiler::Sha2TranspilerExtension; + use openvm_sha2_circuit::Sha2Rv32Config; + use openvm_sha2_transpiler::Sha2TranspilerExtension; use openvm_stark_sdk::p3_baby_bear::BabyBear; use openvm_toolchain_tests::{build_example_program_at_path, get_programs_dir}; use openvm_transpiler::{transpiler::Transpiler, FromElf}; diff --git a/extensions/sha256/transpiler/Cargo.toml b/extensions/sha2/transpiler/Cargo.toml similarity index 73% rename from extensions/sha256/transpiler/Cargo.toml rename to extensions/sha2/transpiler/Cargo.toml index 933859f3a8..9eff76a3db 100644 --- a/extensions/sha256/transpiler/Cargo.toml +++ b/extensions/sha2/transpiler/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "openvm-sha256-transpiler" +name = "openvm-sha2-transpiler" version.workspace = true authors.workspace = true edition.workspace = true -description = "Transpiler extension for sha256" +description = "Transpiler extension for SHA-2" [dependencies] openvm-stark-backend = { workspace = true } openvm-instructions = { workspace = true } openvm-transpiler = { workspace = true } rrs-lib = { workspace = true } -openvm-sha256-guest = { workspace = true } +openvm-sha2-guest = { workspace = true } openvm-instructions-derive = { workspace = true } strum = { workspace = true } diff --git a/extensions/sha256/transpiler/src/lib.rs b/extensions/sha2/transpiler/src/lib.rs similarity index 97% rename from extensions/sha256/transpiler/src/lib.rs rename to extensions/sha2/transpiler/src/lib.rs index 532e3d2828..89249ee026 100644 --- a/extensions/sha256/transpiler/src/lib.rs +++ b/extensions/sha2/transpiler/src/lib.rs @@ -1,6 +1,6 @@ use openvm_instructions::{riscv::RV32_MEMORY_AS, LocalOpcode}; use openvm_instructions_derive::LocalOpcode; -use openvm_sha256_guest::{Sha2BaseFunct7, OPCODE, SHA2_FUNCT3}; +use openvm_sha2_guest::{Sha2BaseFunct7, OPCODE, SHA2_FUNCT3}; use openvm_stark_backend::p3_field::PrimeField32; use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput}; use rrs_lib::instruction_formats::RType; diff --git a/extensions/sha256/circuit/src/lib.rs b/extensions/sha256/circuit/src/lib.rs deleted file mode 100644 index fe0844f902..0000000000 --- a/extensions/sha256/circuit/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod sha256_chip; -pub use sha256_chip::*; - -mod extension; -pub use extension::*; From 376021bf829e4c7f744b2b25455d47c0df1c6687 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 12:55:27 -0400 Subject: [PATCH 16/27] Rename sha-macros and move it to openvm-circuit-primitives-derive --- .../{sha-macros => cols-ref-macro}/Cargo.toml | 2 +- .../{sha-macros => cols-ref-macro}/src/lib.rs | 0 .../tests/aligned_borrow.rs | 0 .../tests/arrays.rs | 0 .../tests/const-len-arrays.rs | 0 .../tests/flags.rs | 0 .../tests/nested.rs | 0 .../tests/simple.rs | 0 .../tests/test_config.rs | 0 .../tests/work-vars.rs | 0 crates/circuits/primitives/derive/Cargo.toml | 10 +- .../primitives/derive/src/cols_ref.rs | 698 ++++++++++++++++++ crates/circuits/primitives/derive/src/lib.rs | 33 + .../primitives/derive/tests/test_cols_ref.rs | 1 + crates/circuits/sha2-air/Cargo.toml | 2 +- crates/circuits/sha2-air/src/columns.rs | 2 +- extensions/sha2/circuit/Cargo.toml | 1 - .../sha2/circuit/src/sha2_chip/columns.rs | 2 +- 18 files changed, 745 insertions(+), 6 deletions(-) rename crates/circuits/{sha-macros => cols-ref-macro}/Cargo.toml (94%) rename crates/circuits/{sha-macros => cols-ref-macro}/src/lib.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/aligned_borrow.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/arrays.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/const-len-arrays.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/flags.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/nested.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/simple.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/test_config.rs (100%) rename crates/circuits/{sha-macros => cols-ref-macro}/tests/work-vars.rs (100%) create mode 100644 crates/circuits/primitives/derive/src/cols_ref.rs create mode 100644 crates/circuits/primitives/derive/tests/test_cols_ref.rs diff --git a/crates/circuits/sha-macros/Cargo.toml b/crates/circuits/cols-ref-macro/Cargo.toml similarity index 94% rename from crates/circuits/sha-macros/Cargo.toml rename to crates/circuits/cols-ref-macro/Cargo.toml index 1abe551abd..8bf47baad2 100644 --- a/crates/circuits/sha-macros/Cargo.toml +++ b/crates/circuits/cols-ref-macro/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "openvm-sha-macros" +name = "todo-delete" version.workspace = true authors.workspace = true edition.workspace = true diff --git a/crates/circuits/sha-macros/src/lib.rs b/crates/circuits/cols-ref-macro/src/lib.rs similarity index 100% rename from crates/circuits/sha-macros/src/lib.rs rename to crates/circuits/cols-ref-macro/src/lib.rs diff --git a/crates/circuits/sha-macros/tests/aligned_borrow.rs b/crates/circuits/cols-ref-macro/tests/aligned_borrow.rs similarity index 100% rename from crates/circuits/sha-macros/tests/aligned_borrow.rs rename to crates/circuits/cols-ref-macro/tests/aligned_borrow.rs diff --git a/crates/circuits/sha-macros/tests/arrays.rs b/crates/circuits/cols-ref-macro/tests/arrays.rs similarity index 100% rename from crates/circuits/sha-macros/tests/arrays.rs rename to crates/circuits/cols-ref-macro/tests/arrays.rs diff --git a/crates/circuits/sha-macros/tests/const-len-arrays.rs b/crates/circuits/cols-ref-macro/tests/const-len-arrays.rs similarity index 100% rename from crates/circuits/sha-macros/tests/const-len-arrays.rs rename to crates/circuits/cols-ref-macro/tests/const-len-arrays.rs diff --git a/crates/circuits/sha-macros/tests/flags.rs b/crates/circuits/cols-ref-macro/tests/flags.rs similarity index 100% rename from crates/circuits/sha-macros/tests/flags.rs rename to crates/circuits/cols-ref-macro/tests/flags.rs diff --git a/crates/circuits/sha-macros/tests/nested.rs b/crates/circuits/cols-ref-macro/tests/nested.rs similarity index 100% rename from crates/circuits/sha-macros/tests/nested.rs rename to crates/circuits/cols-ref-macro/tests/nested.rs diff --git a/crates/circuits/sha-macros/tests/simple.rs b/crates/circuits/cols-ref-macro/tests/simple.rs similarity index 100% rename from crates/circuits/sha-macros/tests/simple.rs rename to crates/circuits/cols-ref-macro/tests/simple.rs diff --git a/crates/circuits/sha-macros/tests/test_config.rs b/crates/circuits/cols-ref-macro/tests/test_config.rs similarity index 100% rename from crates/circuits/sha-macros/tests/test_config.rs rename to crates/circuits/cols-ref-macro/tests/test_config.rs diff --git a/crates/circuits/sha-macros/tests/work-vars.rs b/crates/circuits/cols-ref-macro/tests/work-vars.rs similarity index 100% rename from crates/circuits/sha-macros/tests/work-vars.rs rename to crates/circuits/cols-ref-macro/tests/work-vars.rs diff --git a/crates/circuits/primitives/derive/Cargo.toml b/crates/circuits/primitives/derive/Cargo.toml index 06d4c00aed..cde8f40f69 100644 --- a/crates/circuits/primitives/derive/Cargo.toml +++ b/crates/circuits/primitives/derive/Cargo.toml @@ -14,4 +14,12 @@ proc-macro = true [dependencies] syn = { version = "2.0", features = ["parsing"] } quote = "1.0" -itertools = { workspace = true } +itertools = { workspace = true, default-features = true } +proc-macro2 = "1.0" + +[dev-dependencies] +openvm-sha2-air = { workspace = true } +ndarray.workspace = true + +[package.metadata.cargo-shear] +ignored = ["ndarray"] diff --git a/crates/circuits/primitives/derive/src/cols_ref.rs b/crates/circuits/primitives/derive/src/cols_ref.rs new file mode 100644 index 0000000000..fb623af737 --- /dev/null +++ b/crates/circuits/primitives/derive/src/cols_ref.rs @@ -0,0 +1,698 @@ +use itertools::Itertools; +use proc_macro::TokenStream; +use quote::{format_ident, quote}; +use syn::{parse_macro_input, parse_quote, DeriveInput}; + +pub fn cols_ref_impl( + derive_input: DeriveInput, + config: proc_macro2::Ident, +) -> 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]; + + let const_generics = generics.const_params().map(|p| &p.ident).collect_vec(); + + 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, &const_generics)) + .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(), &config); + + let from_mut_impl = make_from_mut(struct_info, &config)?; + + let mut_field_infos: Vec = data_struct + .fields + .iter() + .map(|f| get_mut_cols_ref_fields(f, generic_type, &const_generics)) + .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, &config); + + 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, config: &proc_macro2::Ident) -> 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 + #[derive(Debug)] + #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 ),* + } + } + + // TODO: make this return the size in bytes (to support fields of constant size) + // returns number of cells in the struct (where each cell has type T) + pub const fn width() -> usize { + 0 #( + #length_exprs )* + } + } + } +} + +fn make_from_mut( + struct_info: StructInfo, + config: &proc_macro2::Ident, +) -> Result { + let StructInfo { + name, + vis: _, + generic_type, + field_infos: _, + fields, + from_args: _, + derive_clone: _, + } = struct_info; + + let from_mut_impl = fields + .iter() + .map(|f| { + let ident = f.ident.clone().unwrap(); + + let derives_aligned_borrow = f + .attrs + .iter() + .any(|attr| attr.path().is_ident("aligned_borrow")); + + let is_array = matches!(f.ty, syn::Type::Array(_)); + + if is_array { + Ok(quote! { + other.#ident.view() + }) + } else if derives_aligned_borrow { + Ok(quote! { + other.#ident + }) + } else if is_columns_struct(&f.ty) { + // 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 if is_generic_type(&f.ty, &generic_type) { + Ok(quote! { + &other.#ident + }) + } else { + panic!("Unsupported field 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! { + // lifetime 'b is used in from_mut to allow more flexible lifetime of return value + impl<'b, #generic_type> #name<'b, #generic_type> { + pub fn from_mut<'a, C: #config>(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, + const_generics: &[&syn::Ident], +) -> Result { + let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); + let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); + + let derives_aligned_borrow = f + .attrs + .iter() + .any(|attr| attr.path().is_ident("aligned_borrow")); + + let has_plain_array_attribute = f.attrs.iter().any(|attr| attr.path().is_ident("array")); + let is_array = matches!(f.ty, syn::Type::Array(_)); + + if has_plain_array_attribute && !is_array { + panic!("field marked with `plain_array` attribute must be an array"); + } + + if is_array { + let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); + debug_assert!( + !dims.is_empty(), + "Array field must have at least one dimension" + ); + + let ndarray_ident: syn::Ident = format_ident!("ArrayView{}", dims.len()); + let ndarray_type: syn::Type = parse_quote! { + ndarray::#ndarray_ident<'a, #elem_type> + }; + + // dimensions of the array in terms of number of cells + let dim_exprs = dims + .iter() + .map(|d| match d { + // need to prepend C:: for const generic array dimensions + Dimension::ConstGeneric(expr) => quote! { C::#expr }, + Dimension::Other(expr) => quote! { #expr }, + }) + .collect_vec(); + + if has_plain_array_attribute { + Err("unsupported currently".to_string()) + /* + debug_assert!( + dims.len() == 1, + "field marked with `plain_array` attribute must be a 1D array" + ); + + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + + Ok(FieldInfo { + ty: parse_quote! { + & #f.ty + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var = #slice_var.try_into().unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + */ + } else if derives_aligned_borrow { + let length_expr = quote! { + <#elem_type>::width() #(* #dim_exprs)* + }; + + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var: &[#elem_type] = unsafe { &*(#slice_var as *const [T] as *const [#elem_type]) }; + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else if is_columns_struct(&elem_type) { + panic!("Arrays of columns structs are currently not supported"); + } else if is_generic_type(&elem_type, generic_type) { + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at(#length_expr); + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else { + panic!("Unsupported field type: {:?}", f.ty); + } + } else if derives_aligned_borrow { + // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) + let f_ty = &f.ty; + Ok(FieldInfo { + ty: parse_quote! { + &'a #f_ty + }, + length_expr: quote! { + <#f_ty>::width() + }, + prepare_subslice: quote! { + let #length_var = <#f_ty>::width(); + let (#slice_var, slice) = slice.split_at(#length_var); + }, + initializer: quote! { + { + use core::borrow::Borrow; + #slice_var.borrow() + } + }, + }) + } else if is_columns_struct(&f.ty) { + let const_cols_ref_type = get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }); + Ok(FieldInfo { + ty: parse_quote! { + #const_cols_ref_type + }, + length_expr: quote! { + <#const_cols_ref_type>::width::() + }, + prepare_subslice: quote! { + let #length_var = <#const_cols_ref_type>::width::(); + let (#slice_var, slice) = slice.split_at(#length_var); + let #slice_var = <#const_cols_ref_type>::from::(#slice_var); + }, + initializer: quote! { + #slice_var + }, + }) + } else if is_generic_type(&f.ty, generic_type) { + 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 { + panic!("Unsupported field type: {:?}", f.ty); + } +} + +// Prepare the fields for the mut ColsRef struct +fn get_mut_cols_ref_fields( + f: &syn::Field, + generic_type: &syn::TypeParam, + const_generics: &[&syn::Ident], +) -> Result { + let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); + let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); + + let derives_aligned_borrow = f + .attrs + .iter() + .any(|attr| attr.path().is_ident("aligned_borrow")); + + let is_array = matches!(f.ty, syn::Type::Array(_)); + + if is_array { + let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); + debug_assert!( + !dims.is_empty(), + "Array field must have at least one dimension" + ); + + let ndarray_ident: syn::Ident = format_ident!("ArrayViewMut{}", dims.len()); + let ndarray_type: syn::Type = parse_quote! { + ndarray::#ndarray_ident<'a, #elem_type> + }; + + // dimensions of the array in terms of number of cells + let dim_exprs = dims + .iter() + .map(|d| match d { + // need to prepend C:: for const generic array dimensions + Dimension::ConstGeneric(expr) => quote! { C::#expr }, + Dimension::Other(expr) => quote! { #expr }, + }) + .collect_vec(); + + if derives_aligned_borrow { + let length_expr = quote! { + <#elem_type>::width() #(* #dim_exprs)* + }; + + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at_mut (#length_expr); + let #slice_var: &mut [#elem_type] = unsafe { &mut *(#slice_var as *mut [T] as *mut [#elem_type]) }; + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else if is_columns_struct(&elem_type) { + panic!("Arrays of columns structs are currently not supported"); + } else if is_generic_type(&elem_type, generic_type) { + let length_expr = quote! { + 1 #(* #dim_exprs)* + }; + Ok(FieldInfo { + ty: parse_quote! { + #ndarray_type + }, + length_expr: length_expr.clone(), + prepare_subslice: quote! { + let (#slice_var, slice) = slice.split_at_mut(#length_expr); + let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); + }, + initializer: quote! { + #slice_var + }, + }) + } else { + panic!("Unsupported field type: {:?}", f.ty); + } + } else if derives_aligned_borrow { + // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) + let f_ty = &f.ty; + Ok(FieldInfo { + ty: parse_quote! { + &'a mut #f_ty + }, + length_expr: quote! { + <#f_ty>::width() + }, + prepare_subslice: quote! { + let #length_var = <#f_ty>::width(); + let (#slice_var, slice) = slice.split_at_mut(#length_var); + }, + initializer: quote! { + { + use core::borrow::BorrowMut; + #slice_var.borrow_mut() + } + }, + }) + } else if is_columns_struct(&f.ty) { + let mut_cols_ref_type = get_mut_cols_ref_type(&f.ty, generic_type); + Ok(FieldInfo { + ty: parse_quote! { + #mut_cols_ref_type + }, + length_expr: quote! { + <#mut_cols_ref_type>::width::() + }, + prepare_subslice: quote! { + let #length_var = <#mut_cols_ref_type>::width::(); + let (#slice_var, slice) = slice.split_at_mut(#length_var); + let #slice_var = <#mut_cols_ref_type>::from::(#slice_var); + }, + initializer: quote! { + #slice_var + }, + }) + } else if is_generic_type(&f.ty, generic_type) { + Ok(FieldInfo { + ty: parse_quote! { + &'a mut #generic_type + }, + length_expr: quote! { + 1 + }, + prepare_subslice: quote! { + let #length_var = 1; + let (#slice_var, slice) = slice.split_at_mut(#length_var); + }, + initializer: quote! { + &mut #slice_var[0] + }, + }) + } else { + panic!("Unsupported field type: {:?}", f.ty); + } +} + +fn is_columns_struct(ty: &syn::Type) -> bool { + if let syn::Type::Path(type_path) = ty { + type_path + .path + .segments + .iter() + .last() + .map(|s| s.ident.to_string().ends_with("Cols")) + .unwrap_or(false) + } else { + false + } +} + +// 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, +) -> syn::TypePath { + if !is_columns_struct(ty) { + panic!("Expected a columns struct, got {:?}", ty); + } + + if let syn::Type::Path(type_path) = ty { + let s = type_path.path.segments.iter().last().unwrap(); + 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> + }; + const_cols_ref_type + } else { + panic!("is_columns_struct returned true for type {:?} but the last segment is not a columns struct", ty); + } + } else { + panic!( + "is_columns_struct returned true but the type {:?} is not a path", + ty + ); + } +} + +// 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) -> syn::TypePath { + if !is_columns_struct(ty) { + panic!("Expected a columns struct, got {:?}", ty); + } + + if let syn::Type::Path(type_path) = ty { + let s = type_path.path.segments.iter().last().unwrap(); + 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> + }; + mut_cols_ref_type + } else { + panic!("is_columns_struct returned true for type {:?} but the last segment is not a columns struct", ty); + } + } else { + panic!( + "is_columns_struct returned true but the type {:?} is not a path", + ty + ); + } +} + +fn is_generic_type(ty: &syn::Type, generic_type: &syn::TypeParam) -> bool { + if let syn::Type::Path(type_path) = ty { + if type_path.path.segments.len() == 1 { + type_path + .path + .segments + .iter() + .last() + .map(|s| s.ident == generic_type.ident) + .unwrap_or(false) + } else { + false + } + } else { + false + } +} + +// Type of array dimension +enum Dimension { + ConstGeneric(syn::Expr), + Other(syn::Expr), +} + +// Describes a nested array +struct ArrayInfo { + dims: Vec, + elem_type: syn::Type, +} + +fn get_array_info(ty: &syn::Type, const_generics: &[&syn::Ident]) -> ArrayInfo { + let dims = get_dims(ty, const_generics); + let elem_type = get_elem_type(ty); + ArrayInfo { dims, elem_type } +} + +fn get_elem_type(ty: &syn::Type) -> syn::Type { + match ty { + syn::Type::Array(array) => get_elem_type(array.elem.as_ref()), + syn::Type::Path(_) => ty.clone(), + _ => panic!("Unsupported type: {:?}", ty), + } +} + +fn get_dims(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { + get_dims_impl(ty, const_generics) + .into_iter() + .rev() + .collect() +} + +fn get_dims_impl(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { + match ty { + syn::Type::Array(array) => { + let mut dims = get_dims_impl(array.elem.as_ref(), const_generics); + match &array.len { + syn::Expr::Path(syn::ExprPath { path, .. }) => { + let len_ident = path.get_ident(); + if len_ident.is_some() && const_generics.contains(&len_ident.unwrap()) { + dims.push(Dimension::ConstGeneric(array.len.clone())); + } else { + dims.push(Dimension::Other(array.len.clone())); + } + } + syn::Expr::Lit(expr_lit) => dims.push(Dimension::Other(expr_lit.clone().into())), + _ => panic!("Unsupported array length type"), + } + dims + } + syn::Type::Path(_) => Vec::new(), + _ => panic!("Unsupported field type"), + } +} diff --git a/crates/circuits/primitives/derive/src/lib.rs b/crates/circuits/primitives/derive/src/lib.rs index 1cece4e3fb..ced79f7f9c 100644 --- a/crates/circuits/primitives/derive/src/lib.rs +++ b/crates/circuits/primitives/derive/src/lib.rs @@ -7,6 +7,9 @@ use proc_macro::TokenStream; use quote::quote; use syn::{parse_macro_input, Data, DeriveInput, Fields, GenericParam, LitStr, Meta}; +mod cols_ref; +use cols_ref::cols_ref_impl; + #[proc_macro_derive(AlignedBorrow)] pub fn aligned_borrow_derive(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -398,3 +401,33 @@ pub fn bytes_stateful_derive(input: TokenStream) -> TokenStream { _ => unimplemented!(), } } + +#[proc_macro_derive(ColsRef, attributes(aligned_borrow, config, plain_array))] +pub fn cols_ref(input: TokenStream) -> TokenStream { + let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput); + + let config = derive_input + .attrs + .iter() + .find(|attr| attr.path().is_ident("config")); + if config.is_none() { + return syn::Error::new(derive_input.ident.span(), "Config attribute is required") + .to_compile_error() + .into(); + } + let config: proc_macro2::Ident = config + .unwrap() + .parse_args() + .expect("Failed to parse config"); + + let span = derive_input.ident.span(); + let res = cols_ref_impl(derive_input, config); + res.map_or_else( + |err| { + syn::Error::new(span, err.to_string()) + .to_compile_error() + .into() + }, + |ok| ok.into(), + ) +} diff --git a/crates/circuits/primitives/derive/tests/test_cols_ref.rs b/crates/circuits/primitives/derive/tests/test_cols_ref.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/circuits/primitives/derive/tests/test_cols_ref.rs @@ -0,0 +1 @@ + diff --git a/crates/circuits/sha2-air/Cargo.toml b/crates/circuits/sha2-air/Cargo.toml index 531ae34e74..65d1cb5814 100644 --- a/crates/circuits/sha2-air/Cargo.toml +++ b/crates/circuits/sha2-air/Cargo.toml @@ -7,9 +7,9 @@ edition.workspace = true [dependencies] openvm-circuit-primitives = { workspace = true } openvm-stark-backend = { workspace = true } +openvm-circuit-primitives-derive = { workspace = true } sha2 = { version = "0.10", features = ["compress"] } rand.workspace = true -openvm-sha-macros = { workspace = true } ndarray.workspace = true [dev-dependencies] diff --git a/crates/circuits/sha2-air/src/columns.rs b/crates/circuits/sha2-air/src/columns.rs index 829892aaa0..c80dc372ff 100644 --- a/crates/circuits/sha2-air/src/columns.rs +++ b/crates/circuits/sha2-air/src/columns.rs @@ -1,7 +1,7 @@ //! WARNING: the order of fields in the structs is important, do not change it use openvm_circuit_primitives::utils::not; -use openvm_sha_macros::ColsRef; +use openvm_circuit_primitives_derive::ColsRef; use openvm_stark_backend::p3_field::FieldAlgebra; use crate::Sha2Config; diff --git a/extensions/sha2/circuit/Cargo.toml b/extensions/sha2/circuit/Cargo.toml index 48301332b0..6e55ac56bd 100644 --- a/extensions/sha2/circuit/Cargo.toml +++ b/extensions/sha2/circuit/Cargo.toml @@ -16,7 +16,6 @@ openvm-instructions = { workspace = true } openvm-sha2-transpiler = { workspace = true } openvm-rv32im-circuit = { workspace = true } openvm-sha2-air = { workspace = true } -openvm-sha-macros = { workspace = true } derive-new.workspace = true derive_more = { workspace = true, features = ["from"] } diff --git a/extensions/sha2/circuit/src/sha2_chip/columns.rs b/extensions/sha2/circuit/src/sha2_chip/columns.rs index 1f1410a119..96b8313476 100644 --- a/extensions/sha2/circuit/src/sha2_chip/columns.rs +++ b/extensions/sha2/circuit/src/sha2_chip/columns.rs @@ -4,12 +4,12 @@ use openvm_circuit::{ arch::ExecutionState, system::memory::offline_checker::{MemoryBaseAuxCols, MemoryReadAuxCols}, }; +use openvm_circuit_primitives_derive::ColsRef; use openvm_instructions::riscv::RV32_REGISTER_NUM_LIMBS; use openvm_sha2_air::{ ShaDigestCols, ShaDigestColsRef, ShaDigestColsRefMut, ShaRoundCols, ShaRoundColsRef, ShaRoundColsRefMut, }; -use openvm_sha_macros::ColsRef; use super::SHA_REGISTER_READS; use crate::ShaChipConfig; From 09d6aa0ad89f059848822644d3e02e15d9b023b5 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 14:00:04 -0400 Subject: [PATCH 17/27] Update SHA-2 VM extension spec --- extensions/sha2/circuit/README.md | 55 ++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/extensions/sha2/circuit/README.md b/extensions/sha2/circuit/README.md index 189c0675b8..8c0293d563 100644 --- a/extensions/sha2/circuit/README.md +++ b/extensions/sha2/circuit/README.md @@ -1,26 +1,42 @@ # SHA-2 VM Extension -This crate contains the circuit for the SHA-2 VM extension. +This crate contains circuits for the SHA-2 family of hash functions. +We support SHA-256, SHA-512, and SHA-384. -## SHA-256 Algorithm Summary +## SHA-2 Algorithms Summary -See the [FIPS standard](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf), in particular, section 6.2 for reference. +The SHA-256, SHA-512, and SHA-384 algorithms are similar in structure. +We will first describe the SHA-256 algorithm, and then describe the differences between the three algorithms. + +See the [FIPS standard](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf) for reference. In particular, sections 6.2, 6.4, and 6.5. In short the SHA-256 algorithm works as follows. 1. Pad the message to 512 bits and split it into 512-bit 'blocks'. -2. Initialize a hash state consisting of eight 32-bit words. +2. Initialize a hash state consisting of eight 32-bit words to a specific constant value. 3. For each block, - 1. split the message into 16 32-bit words and produce 48 more 'message schedule' words based on them. - 2. apply 64 'rounds' to update the hash state based on the message schedule. + 1. split the message into 16 32-bit words and produce 48 more words based on them. The 16 message word together with the 48 additional words are called the 'message schedule'. + 2. apply a scrambling function 64 times to the hash state to update it based on the message schedule. We call each update a 'round'. 3. add the previous block's final hash state to the current hash state (modulo `2^32`). 4. The output is the final hash state +The differences with the SHA-512 algorithm are that: +- it uses 64-bit words, 1024-bit blocks, performs 80 rounds, and produces a 512-bit output. +- all the arithmetic is done modulo `2^64`. +- the initial hash state is different. + +The SHA-384 algorithm is almost exactly a truncation of the SHA-512 output to 384 bits. +The only difference is that the initial hash state is different. + ## Design Overview -This chip produces an AIR that consists of 17 rows for each block (512 bits) in the message, and no more rows. -The first 16 rows of each block are called 'round rows', and each of them represents four rounds of the SHA-256 algorithm. -Each row constrains updates to the working variables on each round, and it also constrains the message schedule words based on previous rounds. -The final row is called a 'digest row' and it produces a final hash for the block, computed as the sum of the working variables and the previous block's final hash. +We re-use the same AIR code to produce circuits for all three algorithms. +To achieve this, we parameterize the AIR by constants (such as the word size, number of rounds, and block size) that are specific to each algorithm. + +This chip produces an AIR that consists of $R+1$ rows for each block of the message, and no more rows +(for SHA-256, $R = 16$ and for SHA-512 and SHA-384, $R = 20$). +The first $R$ rows of each block are called 'round rows', and each of them constrains four rounds of the hash algorithm. +Each row constrains updates to the working variables on each round, and also constrains the message schedule words based on previous rounds. +The final row of each block is called a 'digest row' and it produces a final hash for the block, computed as the sum of the working variables and the previous block's final hash. Note that this chip only supports messages of length less than `2^29` bytes. @@ -50,7 +66,7 @@ Since we can reliably constrain values from four rounds ago, we can build up `in The last block of every message should have the `is_last_block` flag set to `1`. Note that `is_last_block` is not constrained to be true for the last block of every message, instead it *defines* what the last block of a message is. -For instance, if we produce an air with 10 blocks and only the last block has `is_last_block = 1` then the constraints will interpret it as a single message of length 10 blocks. +For instance, if we produce a trace with 10 blocks and only the last block has `is_last_block = 1` then the constraints will interpret it as a single message of length 10 blocks. If, however, we set `is_last_block` to true for the 6th block, the trace will be interpreted as hashing two messages, each of length 5 blocks. Note that we do constrain, however, that the very last block of the trace has `is_last_block = 1`. @@ -63,11 +79,11 @@ We use this trick in several places in this chip. ### Block index counter variables -There are two "block index" counter variables in each row of the air named `global_block_idx` and `local_block_idx`. -Both of these variables take on the same value on all 17 rows in a block. +There are two "block index" counter variables in each row named `global_block_idx` and `local_block_idx`. +Both of these variables take on the same value on all $R+1$ rows in a block. The `global_block_idx` is the index of the block in the entire trace. -The very first 17 rows in the trace will have `global_block_idx = 1` and the counter will increment by 1 between blocks. +The very first block in the trace will have `global_block_idx = 1` on each row and the counter will increment by 1 between blocks. The padding rows will all have `global_block_idx = 0`. The `global_block_idx` is used in interaction constraints to constrain the value of `hash` between blocks. @@ -79,15 +95,16 @@ The `local_block_idx` is used to calculate the length of the message processed s ### VM air vs SubAir -The SHA-256 VM extension chip uses the `Sha256Air` SubAir to help constrain the SHA-256 hash. -The VM extension air constrains the correctness of the SHA message padding, while the SubAir adds all other constraints related to the hash algorithm. +The SHA-2 VM extension chip uses the `Sha2Air` SubAir to help constrain the appropriate SHA-2 hash algorithm. +The SubAir is also parameterized by the specific SHA-2 variant's constants. +The VM extension AIR constrains the correctness of the message padding, while the SubAir adds all other constraints related to the hash algorithm. The VM extension air also constrains memory reads and writes. ### A gotcha about padding rows There are two senses of the word padding used in the context of this chip and this can be confusing. -First, we use padding to refer to the extra bits added to the message that is input to the SHA-256 algorithm in order to make the input's length a multiple of 512 bits. -So, we may use the term 'padding rows' to refer to round rows that correspond to the padded bits of a message (as in `Sha256VmAir::eval_padding_row`). +First, we use padding to refer to the extra bits added to the message that is input to the hash algorithm in order to make the input's length a multiple of the block size. +So, we may use the term 'padding rows' to refer to round rows that correspond to the padded bits of a message (as in `Sha2VmAir::eval_padding_row`). Second, the dummy rows that are added to the trace to make the trace height a power of 2 are also called padding rows (see the `is_padding_row` flag). In the SubAir, padding row probably means dummy row. -In the VM air, it probably refers to SHA-256 padding. \ No newline at end of file +In the VM air, it probably refers to the message padding. \ No newline at end of file From 70a559a952ecf7548ab045edb66a796ada65d27f Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 14:19:40 -0400 Subject: [PATCH 18/27] Updated the specs --- docs/specs/ISA.md | 6 +++--- docs/specs/RISCV.md | 8 ++++---- docs/specs/isa-table.md | 8 ++++---- docs/specs/transpiler.md | 2 +- extensions/sha2/circuit/README.md | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/specs/ISA.md b/docs/specs/ISA.md index 959059c89e..a430cd1667 100644 --- a/docs/specs/ISA.md +++ b/docs/specs/ISA.md @@ -6,7 +6,7 @@ This specification describes the overall architecture and default VM extensions - [RV32IM](#rv32im-extension): An extension supporting the 32-bit RISC-V ISA with multiplication. - [Native](#native-extension): An extension supporting native field arithmetic for proof recursion and aggregation. - [Keccak-256](#keccak-extension): An extension implementing the Keccak-256 hash function compatibly with RISC-V memory. -- [SHA2](#sha2-extension): An extension implementing the SHA2-256 and SHA2-512 hash functions compatibly with RISC-V memory. +- [SHA2](#sha2-extension): An extension implementing the SHA-256, SHA-512, and SHA-384 hash functions compatibly with RISC-V memory. - [BigInt](#bigint-extension): An extension supporting 256-bit signed and unsigned integer arithmetic, including multiplication. This extension respects the RISC-V memory format. - [Algebra](#algebra-extension): An extension supporting modular arithmetic over arbitrary fields and their complex @@ -538,9 +538,9 @@ all memory cells are constrained to be bytes. | -------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- | | KECCAK256_RV32 | `a,b,c,1,2` | `[r32{0}(a):32]_2 = keccak256([r32{0}(b)..r32{0}(b)+r32{0}(c)]_2)`. Performs memory accesses with block size `4`. | -### SHA2 Extension +### SHA-2 Extension -The SHA2 extension supports the SHA2-256 and SHA2-512 hash functions. The extension operates on address spaces `1` and `2`, +The SHA-2 extension supports the SHA-256 and SHA-512 hash functions. The extension operates on address spaces `1` and `2`, meaning all memory cells are constrained to be bytes. | Name | Operands | Description | diff --git a/docs/specs/RISCV.md b/docs/specs/RISCV.md index 6b79d3d962..d9f1e5cb38 100644 --- a/docs/specs/RISCV.md +++ b/docs/specs/RISCV.md @@ -5,7 +5,7 @@ The default VM extensions that support transpilation are: - [RV32IM](#rv32im-extension): An extension supporting the 32-bit RISC-V ISA with multiplication. - [Keccak-256](#keccak-extension): An extension implementing the Keccak-256 hash function compatibly with RISC-V memory. -- [SHA2](#sha2-extension): An extension implementing the SHA2-256 and SHA2-512 hash functions compatibly with RISC-V memory. +- [SHA2](#sha2-extension): An extension implementing the SHA-256, SHA-512, and SHA-384 hash functions compatibly with RISC-V memory. - [BigInt](#bigint-extension): An extension supporting 256-bit signed and unsigned integer arithmetic, including multiplication. This extension respects the RISC-V memory format. - [Algebra](#algebra-extension): An extension supporting modular arithmetic over arbitrary fields and their complex field extensions. This extension respects the RISC-V memory format. - [Elliptic curve](#elliptic-curve-extension): An extension for elliptic curve operations over Weierstrass curves, including addition and doubling. This can be used to implement multi-scalar multiplication and ECDSA scalar multiplication. This extension respects the RISC-V memory format. @@ -78,13 +78,13 @@ the guest must take care to validate all data and account for behavior in cases | ----------- | --- | ----------- | ------ | ------ | ------------------------------------------- | | keccak256 | R | 0001011 | 100 | 0x0 | `[rd:32]_2 = keccak256([rs1..rs1 + rs2]_2)` | -## SHA2 Extension +## SHA-2 Extension | RISC-V Inst | FMT | opcode[6:0] | funct3 | funct7 | RISC-V description and notes | | ----------- | --- | ----------- | ------ | ------ | ---------------------------------------- | | sha256 | R | 0001011 | 100 | 0x1 | `[rd:32]_2 = sha256([rs1..rs1 + rs2]_2)` | -| sha512 | R | 0001011 | 100 | 0x2 | `[rd:32]_2 = sha512([rs1..rs1 + rs2]_2)` | -| sha384 | R | 0001011 | 100 | 0x3 | `[rd:32]_2 = sha384([rs1..rs1 + rs2]_2)` | +| sha512 | R | 0001011 | 100 | 0x2 | `[rd:64]_2 = sha512([rs1..rs1 + rs2]_2)` | +| sha384 | R | 0001011 | 100 | 0x3 | `[rd:64]_2 = sha384([rs1..rs1 + rs2]_2)`. Last 16 bytes will be set to zeros. | ## BigInt Extension diff --git a/docs/specs/isa-table.md b/docs/specs/isa-table.md index a96b59e6bb..8595dab9cd 100644 --- a/docs/specs/isa-table.md +++ b/docs/specs/isa-table.md @@ -128,15 +128,15 @@ In the tables below, we provide the mapping between the `LocalOpcode` and `Phant | ------------- | ---------- | ------------- | | Keccak | `Rv32KeccakOpcode::KECCAK256` | KECCAK256_RV32 | -## SHA2-256 Extension +## SHA-2 Extension #### Instructions | VM Extension | `LocalOpcode` | ISA Instruction | | ------------- | ---------- | ------------- | -| SHA2-256 | `Rv32Sha2Opcode::SHA256` | SHA256_RV32 | -| SHA2-512 | `Rv32Sha2Opcode::SHA512` | SHA512_RV32 | -| SHA2-384 | `Rv32Sha2Opcode::SHA384` | SHA384_RV32 | +| SHA-2 | `Rv32Sha2Opcode::SHA256` | SHA256_RV32 | +| SHA-2 | `Rv32Sha2Opcode::SHA512` | SHA512_RV32 | +| SHA-2 | `Rv32Sha2Opcode::SHA384` | SHA384_RV32 | ## BigInt Extension diff --git a/docs/specs/transpiler.md b/docs/specs/transpiler.md index 8afa9c3d7f..eacd2442cf 100644 --- a/docs/specs/transpiler.md +++ b/docs/specs/transpiler.md @@ -151,7 +151,7 @@ Each VM extension's behavior is specified below. | ----------- | -------------------------------------------------- | | keccak256 | KECCAK256_RV32 `ind(rd), ind(rs1), ind(rs2), 1, 2` | -### SHA2 Extension +### SHA-2 Extension | RISC-V Inst | OpenVM Instruction | | ----------- | ----------------------------------------------- | diff --git a/extensions/sha2/circuit/README.md b/extensions/sha2/circuit/README.md index 8c0293d563..317c913fe5 100644 --- a/extensions/sha2/circuit/README.md +++ b/extensions/sha2/circuit/README.md @@ -29,7 +29,7 @@ The only difference is that the initial hash state is different. ## Design Overview -We re-use the same AIR code to produce circuits for all three algorithms. +We reuse the same AIR code to produce circuits for all three algorithms. To achieve this, we parameterize the AIR by constants (such as the word size, number of rounds, and block size) that are specific to each algorithm. This chip produces an AIR that consists of $R+1$ rows for each block of the message, and no more rows From 6a837f0225b164f40d8fd375680032db7f60db6f Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 14:19:47 -0400 Subject: [PATCH 19/27] Updated the book --- book/src/SUMMARY.md | 2 +- book/src/custom-extensions/overview.md | 4 ++-- book/src/custom-extensions/sha2.md | 30 +++++++++++++++----------- book/src/introduction.md | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 579bc70136..490971b050 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -19,7 +19,7 @@ - [Overview](./custom-extensions/overview.md) - [Keccak](./custom-extensions/keccak.md) -- [SHA-256](./custom-extensions/sha256.md) +- [SHA-2](./custom-extensions/sha2.md) - [Big Integer](./custom-extensions/bigint.md) - [Algebra (Modular Arithmetic)](./custom-extensions/algebra.md) - [Elliptic Curve Cryptography](./custom-extensions/ecc.md) diff --git a/book/src/custom-extensions/overview.md b/book/src/custom-extensions/overview.md index bfc59f1e55..706a9709cc 100644 --- a/book/src/custom-extensions/overview.md +++ b/book/src/custom-extensions/overview.md @@ -5,7 +5,7 @@ You can seamlessly integrate certain performance-optimized extensions maintained In this chapter, we will explain how to use the following existing extensions: - [`openvm-keccak-guest`](./keccak.md) - Keccak256 hash function. -- [`openvm-sha2-guest`](./sha2.md) - SHA2 hash functions. +- [`openvm-sha2-guest`](./sha2.md) - SHA-2 hash functions. - [`openvm-bigint-guest`](./bigint.md) - Big integer arithmetic for 256-bit signed and unsigned integers. - [`openvm-algebra-guest`](./algebra.md) - Modular arithmetic and complex field extensions. - [`openvm-ecc-guest`](./ecc.md) - Elliptic curve cryptography. @@ -35,7 +35,7 @@ The template `openvm.toml` file is as follows: [app_vm_config.rv32m] [app_vm_config.io] [app_vm_config.keccak] -[app_vm_config.sha256] +[app_vm_config.sha2] [app_vm_config.native] [app_vm_config.bigint] [app_vm_config.modular] diff --git a/book/src/custom-extensions/sha2.md b/book/src/custom-extensions/sha2.md index 7b1e39be51..ba3727d563 100644 --- a/book/src/custom-extensions/sha2.md +++ b/book/src/custom-extensions/sha2.md @@ -1,36 +1,40 @@ -# SHA-256 +# SHA-2 -The OpenVM SHA-256 extension provides tools for using the SHA-256 hash function. Refer [here](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf) for more details on SHA-256. -The functional part is provided by the `openvm-sha256-guest` crate, which is a guest library that can be used in any OpenVM program. +The OpenVM SHA-2 extension provides tools for using the SHA-256, SHA-512, and SHA-384 hash functions. Refer [here](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf) for more details on the SHA-2 family of hash functions. +The functional part is provided by the `openvm-sha2-guest` crate, which is a guest library that can be used in any OpenVM program. ## Functions for guest code -The OpenVM SHA-256Guest extension provides two functions for using in your guest code: +The OpenVM SHA-2 Guest extension provides three pairs of functions for using in your guest code: - `sha256(input: &[u8]) -> [u8; 32]`: Computes the SHA-256 hash of the input data and returns it as an array of 32 bytes. -- `set_sha256(input: &[u8], output: &mut [u8; 32])`: Sets the output to the SHA-256 hash of the input data into the provided output buffer. +- `set_sha256(input: &[u8], output: &mut [u8; 32])`: Sets the provided output buffer to the SHA-256 hash of the input data. +- `sha512(input: &[u8]) -> [u8; 64]`: Computes the SHA-512 hash of the input data and returns it as an array of 64 bytes. +- `set_sha512(input: &[u8], output: &mut [u8; 64])`: Sets the provided output buffer to the SHA-512 hash of the input data. +- `sha384(input: &[u8]) -> [u8; 48]`: Computes the SHA-384 hash of the input data and returns it as an array of 48 bytes. +- `set_sha384(input: &[u8], output: &mut [u8; 64])`: Sets the first 48 bytes of the provided output buffer to the SHA-384 hash of the input data and sets the rest of the buffer to zero. -See the full example [here](https://github.com/openvm-org/openvm/blob/main/examples/sha256/src/main.rs). +See the full example [here](https://github.com/openvm-org/openvm/blob/main/examples/sha2/src/main.rs). ### Example ```rust,no_run,noplayground -{{ #include ../../../examples/sha256/src/main.rs:imports }} -{{ #include ../../../examples/sha256/src/main.rs:main }} +{{ #include ../../../examples/sha2/src/main.rs:imports }} +{{ #include ../../../examples/sha2/src/main.rs:main }} ``` -To be able to import the `sha256` function, add the following to your `Cargo.toml` file: +To be able to import the `shaXXX` functions, add the following to your `Cargo.toml` file: ```toml -openvm-sha256-guest = { git = "https://github.com/openvm-org/openvm.git" } +openvm-sha2-guest = { git = "https://github.com/openvm-org/openvm.git" } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } ``` ## External Linking -The SHA-256 guest extension also provides another way to use the intrinsic SHA-256 implementation. It provides a function that is meant to be linked to other external libraries. The external libraries can use this function as a hook for the SHA-256 intrinsic. This is enabled only when the target is `zkvm`. +The SHA-2 guest extension also provides another way to use the intrinsic SHA-2 implementations. It provides functions that are meant to be linked to other external libraries. The external libraries can use these functions as hooks for the SHA-2 intrinsics. This is enabled only when the target is `zkvm`. -- `zkvm_sha256_impl(input: *const u8, len: usize, output: *mut u8)`: This function has `C` ABI. It takes in a pointer to the input, the length of the input, and a pointer to the output buffer. +- `zkvm_shaXXX_impl(input: *const u8, len: usize, output: *mut u8)`: where `XXX` is `256`, `512`, or `384`. These functions have `C` ABI. They take in a pointer to the input, the length of the input, and a pointer to the output buffer. In the external library, you can do the following: @@ -59,5 +63,5 @@ fn sha256(input: &[u8]) -> [u8; 32] { For the guest program to build successfully add the following to your `.toml` file: ```toml -[app_vm_config.sha256] +[app_vm_config.sha2] ``` diff --git a/book/src/introduction.md b/book/src/introduction.md index 610faaedf2..40e8c37958 100644 --- a/book/src/introduction.md +++ b/book/src/introduction.md @@ -12,7 +12,7 @@ OpenVM is an open-source zero-knowledge virtual machine (zkVM) framework focused - RISC-V support via RV32IM - A native field arithmetic extension for proof recursion and aggregation - - The Keccak-256 and SHA2-256 hash functions + - The Keccak-256, SHA-256, SHA-512, and SHA-384 hash functions - Int256 arithmetic - Modular arithmetic over arbitrary fields - Elliptic curve operations, including multi-scalar multiplication and ECDSA signature verification, including for the secp256k1 and secp256r1 curves. From 6c14e5ad8045d3bb68256ba83ce61db04f373789 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 14:20:03 -0400 Subject: [PATCH 20/27] Deleted debugging code --- extensions/sha2/circuit/tmp.rs | 585 --------------------------------- 1 file changed, 585 deletions(-) delete mode 100644 extensions/sha2/circuit/tmp.rs diff --git a/extensions/sha2/circuit/tmp.rs b/extensions/sha2/circuit/tmp.rs deleted file mode 100644 index d2f2e9def5..0000000000 --- a/extensions/sha2/circuit/tmp.rs +++ /dev/null @@ -1,585 +0,0 @@ -#[derive(Clone)] -pub struct ShaVmRoundColsRef<'a, T> { - pub control: ShaVmControlColsRef<'a, T>, - pub inner: ShaRoundColsRef<'a, T>, - pub read_aux: &'a MemoryReadAuxCols, -} -impl<'a, T> ShaVmRoundColsRef<'a, T> { - pub fn from(slice: &'a [T]) -> Self { - let control_length = >::width::(); - let (control_slice, slice) = slice.split_at(control_length); - let control_slice = >::from::(control_slice); - let inner_length = >::width::(); - let (inner_slice, slice) = slice.split_at(inner_length); - let inner_slice = >::from::(inner_slice); - let read_aux_length = >::width(); - let (read_aux_slice, slice) = slice.split_at(read_aux_length); - Self { - control: control_slice, - inner: inner_slice, - read_aux: { - use core::borrow::Borrow; - read_aux_slice.borrow() - }, - } - } - pub const fn width() -> usize { - 0 + >::width::() - + >::width::() - + >::width() - } -} -impl<'b, T> ShaVmRoundColsRef<'b, T> { - pub fn from_mut<'a, C: ShaChipConfig>(other: &'b ShaVmRoundColsRefMut<'a, T>) -> Self { - Self { - control: >::from_mut::(&other.control), - inner: >::from_mut::(&other.inner), - read_aux: other.read_aux, - } - } -} -pub struct ShaVmRoundColsRefMut<'a, T> { - pub control: ShaVmControlColsRefMut<'a, T>, - pub inner: ShaRoundColsRefMut<'a, T>, - pub read_aux: &'a mut MemoryReadAuxCols, -} -impl<'a, T> ShaVmRoundColsRefMut<'a, T> { - pub fn from(slice: &'a mut [T]) -> Self { - let control_length = >::width::(); - let (control_slice, slice) = slice.split_at_mut(control_length); - let control_slice = >::from::(control_slice); - let inner_length = >::width::(); - let (inner_slice, slice) = slice.split_at_mut(inner_length); - let inner_slice = >::from::(inner_slice); - let read_aux_length = >::width(); - let (read_aux_slice, slice) = slice.split_at_mut(read_aux_length); - Self { - control: control_slice, - inner: inner_slice, - read_aux: { - use core::borrow::BorrowMut; - read_aux_slice.borrow_mut() - }, - } - } - pub const fn width() -> usize { - 0 + >::width::() - + >::width::() - + >::width() - } -} -#[derive(Clone)] -pub struct ShaVmDigestColsRef<'a, T> { - pub control: ShaVmControlColsRef<'a, T>, - pub inner: ShaDigestColsRef<'a, T>, - pub from_state: &'a ExecutionState, - pub rd_ptr: &'a T, - pub rs1_ptr: &'a T, - pub rs2_ptr: &'a T, - pub dst_ptr: ndarray::ArrayView1<'a, T>, - pub src_ptr: ndarray::ArrayView1<'a, T>, - pub len_data: ndarray::ArrayView1<'a, T>, - pub register_reads_aux: ndarray::ArrayView1<'a, MemoryReadAuxCols>, - pub writes_aux_base: &'a MemoryBaseAuxCols, - pub writes_aux_prev_data: ndarray::ArrayView1<'a, T>, -} -impl<'a, T> ShaVmDigestColsRef<'a, T> { - pub fn from(slice: &'a [T]) -> Self { - let control_length = >::width::(); - let (control_slice, slice) = slice.split_at(control_length); - let control_slice = >::from::(control_slice); - let inner_length = >::width::(); - let (inner_slice, slice) = slice.split_at(inner_length); - let inner_slice = >::from::(inner_slice); - let from_state_length = >::width(); - let (from_state_slice, slice) = slice.split_at(from_state_length); - let rd_ptr_length = 1; - let (rd_ptr_slice, slice) = slice.split_at(rd_ptr_length); - let rs1_ptr_length = 1; - let (rs1_ptr_slice, slice) = slice.split_at(rs1_ptr_length); - let rs2_ptr_length = 1; - let (rs2_ptr_slice, slice) = slice.split_at(rs2_ptr_length); - let (dst_ptr_slice, slice) = slice.split_at(1 * RV32_REGISTER_NUM_LIMBS); - let dst_ptr_slice = - ndarray::ArrayView1::from_shape((RV32_REGISTER_NUM_LIMBS), dst_ptr_slice).unwrap(); - let (src_ptr_slice, slice) = slice.split_at(1 * RV32_REGISTER_NUM_LIMBS); - let src_ptr_slice = - ndarray::ArrayView1::from_shape((RV32_REGISTER_NUM_LIMBS), src_ptr_slice).unwrap(); - let (len_data_slice, slice) = slice.split_at(1 * RV32_REGISTER_NUM_LIMBS); - let len_data_slice = - ndarray::ArrayView1::from_shape((RV32_REGISTER_NUM_LIMBS), len_data_slice).unwrap(); - let (register_reads_aux_slice, slice) = - slice.split_at(>::width() * SHA_REGISTER_READS); - let register_reads_aux_slice: &[MemoryReadAuxCols] = - unsafe { &*(slice as *const [T] as *const [MemoryReadAuxCols]) }; - let register_reads_aux_slice = - ndarray::ArrayView1::from_shape((SHA_REGISTER_READS), register_reads_aux_slice) - .unwrap(); - let writes_aux_base_length = >::width(); - let (writes_aux_base_slice, slice) = slice.split_at(writes_aux_base_length); - let (writes_aux_prev_data_slice, slice) = slice.split_at(1 * C::WRITE_SIZE); - let writes_aux_prev_data_slice = - ndarray::ArrayView1::from_shape((C::WRITE_SIZE), writes_aux_prev_data_slice).unwrap(); - Self { - control: control_slice, - inner: inner_slice, - from_state: { - use core::borrow::Borrow; - from_state_slice.borrow() - }, - rd_ptr: &rd_ptr_slice[0], - rs1_ptr: &rs1_ptr_slice[0], - rs2_ptr: &rs2_ptr_slice[0], - dst_ptr: dst_ptr_slice, - src_ptr: src_ptr_slice, - len_data: len_data_slice, - register_reads_aux: register_reads_aux_slice, - writes_aux_base: { - use core::borrow::Borrow; - writes_aux_base_slice.borrow() - }, - writes_aux_prev_data: writes_aux_prev_data_slice, - } - } - pub const fn width() -> usize { - 0 + >::width::() - + >::width::() - + >::width() - + 1 - + 1 - + 1 - + 1 * RV32_REGISTER_NUM_LIMBS - + 1 * RV32_REGISTER_NUM_LIMBS - + 1 * RV32_REGISTER_NUM_LIMBS - + >::width() * SHA_REGISTER_READS - + >::width() - + 1 * C::WRITE_SIZE - } -} -impl<'b, T> ShaVmDigestColsRef<'b, T> { - pub fn from_mut<'a, C: ShaChipConfig>(other: &'b ShaVmDigestColsRefMut<'a, T>) -> Self { - Self { - control: >::from_mut::(&other.control), - inner: >::from_mut::(&other.inner), - from_state: other.from_state, - rd_ptr: &other.rd_ptr, - rs1_ptr: &other.rs1_ptr, - rs2_ptr: &other.rs2_ptr, - dst_ptr: other.dst_ptr.view(), - src_ptr: other.src_ptr.view(), - len_data: other.len_data.view(), - register_reads_aux: other.register_reads_aux.view(), - writes_aux_base: other.writes_aux_base, - writes_aux_prev_data: other.writes_aux_prev_data.view(), - } - } -} -pub struct ShaVmDigestColsRefMut<'a, T> { - pub control: ShaVmControlColsRefMut<'a, T>, - pub inner: ShaDigestColsRefMut<'a, T>, - pub from_state: &'a mut ExecutionState, - pub rd_ptr: &'a mut T, - pub rs1_ptr: &'a mut T, - pub rs2_ptr: &'a mut T, - pub dst_ptr: ndarray::ArrayViewMut1<'a, T>, - pub src_ptr: ndarray::ArrayViewMut1<'a, T>, - pub len_data: ndarray::ArrayViewMut1<'a, T>, - pub register_reads_aux: ndarray::ArrayViewMut1<'a, MemoryReadAuxCols>, - pub writes_aux_base: &'a mut MemoryBaseAuxCols, - pub writes_aux_prev_data: ndarray::ArrayViewMut1<'a, T>, -} -impl<'a, T> ShaVmDigestColsRefMut<'a, T> { - pub fn from(slice: &'a mut [T]) -> Self { - let control_length = >::width::(); - let (control_slice, slice) = slice.split_at_mut(control_length); - let control_slice = >::from::(control_slice); - let inner_length = >::width::(); - let (inner_slice, slice) = slice.split_at_mut(inner_length); - let inner_slice = >::from::(inner_slice); - let from_state_length = >::width(); - let (from_state_slice, slice) = slice.split_at_mut(from_state_length); - let rd_ptr_length = 1; - let (rd_ptr_slice, slice) = slice.split_at_mut(rd_ptr_length); - let rs1_ptr_length = 1; - let (rs1_ptr_slice, slice) = slice.split_at_mut(rs1_ptr_length); - let rs2_ptr_length = 1; - let (rs2_ptr_slice, slice) = slice.split_at_mut(rs2_ptr_length); - let (dst_ptr_slice, slice) = slice.split_at_mut(1 * RV32_REGISTER_NUM_LIMBS); - let dst_ptr_slice = - ndarray::ArrayViewMut1::from_shape((RV32_REGISTER_NUM_LIMBS), dst_ptr_slice).unwrap(); - let (src_ptr_slice, slice) = slice.split_at_mut(1 * RV32_REGISTER_NUM_LIMBS); - let src_ptr_slice = - ndarray::ArrayViewMut1::from_shape((RV32_REGISTER_NUM_LIMBS), src_ptr_slice).unwrap(); - let (len_data_slice, slice) = slice.split_at_mut(1 * RV32_REGISTER_NUM_LIMBS); - let len_data_slice = - ndarray::ArrayViewMut1::from_shape((RV32_REGISTER_NUM_LIMBS), len_data_slice).unwrap(); - let (register_reads_aux_slice, slice) = - slice.split_at_mut(>::width() * SHA_REGISTER_READS); - let register_reads_aux_slice: &mut [MemoryReadAuxCols] = - unsafe { &mut *(slice as *mut [T] as *mut [MemoryReadAuxCols]) }; - let register_reads_aux_slice = - ndarray::ArrayViewMut1::from_shape((SHA_REGISTER_READS), register_reads_aux_slice) - .unwrap(); - let writes_aux_base_length = >::width(); - let (writes_aux_base_slice, slice) = slice.split_at_mut(writes_aux_base_length); - let (writes_aux_prev_data_slice, slice) = slice.split_at_mut(1 * C::WRITE_SIZE); - let writes_aux_prev_data_slice = - ndarray::ArrayViewMut1::from_shape((C::WRITE_SIZE), writes_aux_prev_data_slice) - .unwrap(); - Self { - control: control_slice, - inner: inner_slice, - from_state: { - use core::borrow::BorrowMut; - from_state_slice.borrow_mut() - }, - rd_ptr: &mut rd_ptr_slice[0], - rs1_ptr: &mut rs1_ptr_slice[0], - rs2_ptr: &mut rs2_ptr_slice[0], - dst_ptr: dst_ptr_slice, - src_ptr: src_ptr_slice, - len_data: len_data_slice, - register_reads_aux: register_reads_aux_slice, - writes_aux_base: { - use core::borrow::BorrowMut; - writes_aux_base_slice.borrow_mut() - }, - writes_aux_prev_data: writes_aux_prev_data_slice, - } - } - pub const fn width() -> usize { - 0 + >::width::() - + >::width::() - + >::width() - + 1 - + 1 - + 1 - + 1 * RV32_REGISTER_NUM_LIMBS - + 1 * RV32_REGISTER_NUM_LIMBS - + 1 * RV32_REGISTER_NUM_LIMBS - + >::width() * SHA_REGISTER_READS - + >::width() - + 1 * C::WRITE_SIZE - } -} -impl< - 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, - const WRITE_SIZE: usize, - > - core::borrow::Borrow< - ShaVmDigestCols< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - >, - > for [T] -{ - fn borrow( - &self, - ) -> &ShaVmDigestCols< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - > { - if true { - match ( - &self.len(), - &ShaVmDigestCols::< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - >::width(), - ) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - let kind = ::core::panicking::AssertKind::Eq; - ::core::panicking::assert_failed( - kind, - &*left_val, - &*right_val, - ::core::option::Option::None, - ); - } - } - }; - } - let (prefix, shorts, _suffix) = unsafe { - self.align_to::>() - }; - if true { - if !prefix.is_empty() { - { - ::core::panicking::panic_fmt(format_args!("Alignment should match")); - } - } - } - if true { - match (&shorts.len(), &1) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - let kind = ::core::panicking::AssertKind::Eq; - ::core::panicking::assert_failed( - kind, - &*left_val, - &*right_val, - ::core::option::Option::None, - ); - } - } - }; - } - &shorts[0] - } -} -impl< - 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, - const WRITE_SIZE: usize, - > - core::borrow::BorrowMut< - ShaVmDigestCols< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - >, - > for [T] -{ - fn borrow_mut( - &mut self, - ) -> &mut ShaVmDigestCols< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - > { - if true { - match ( - &self.len(), - &ShaVmDigestCols::< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - >::width(), - ) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - let kind = ::core::panicking::AssertKind::Eq; - ::core::panicking::assert_failed( - kind, - &*left_val, - &*right_val, - ::core::option::Option::None, - ); - } - } - }; - } - let (prefix, shorts, _suffix) = unsafe { - self.align_to_mut::>() - }; - if true { - if !prefix.is_empty() { - { - ::core::panicking::panic_fmt(format_args!("Alignment should match")); - } - } - } - if true { - match (&shorts.len(), &1) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - let kind = ::core::panicking::AssertKind::Eq; - ::core::panicking::assert_failed( - kind, - &*left_val, - &*right_val, - ::core::option::Option::None, - ); - } - } - }; - } - &mut shorts[0] - } -} -impl< - 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, - const WRITE_SIZE: usize, - > - ShaVmDigestCols< - T, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - > -{ - pub const fn width() -> usize { - std::mem::size_of::< - ShaVmDigestCols< - u8, - WORD_BITS, - WORD_U8S, - WORD_U16S, - HASH_WORDS, - ROUNDS_PER_ROW, - ROUNDS_PER_ROW_MINUS_ONE, - ROW_VAR_CNT, - WRITE_SIZE, - >, - >() - } -} -#[derive(Clone)] -pub struct ShaVmControlColsRef<'a, T> { - pub len: &'a T, - pub cur_timestamp: &'a T, - pub read_ptr: &'a T, - pub pad_flags: ndarray::ArrayView1<'a, T>, - pub padding_occurred: &'a T, -} -impl<'a, T> ShaVmControlColsRef<'a, T> { - pub fn from(slice: &'a [T]) -> Self { - let len_length = 1; - let (len_slice, slice) = slice.split_at(len_length); - let cur_timestamp_length = 1; - let (cur_timestamp_slice, slice) = slice.split_at(cur_timestamp_length); - let read_ptr_length = 1; - let (read_ptr_slice, slice) = slice.split_at(read_ptr_length); - let (pad_flags_slice, slice) = slice.split_at(1 * 6); - let pad_flags_slice = ndarray::ArrayView1::from_shape((6), pad_flags_slice).unwrap(); - let padding_occurred_length = 1; - let (padding_occurred_slice, slice) = slice.split_at(padding_occurred_length); - Self { - len: &len_slice[0], - cur_timestamp: &cur_timestamp_slice[0], - read_ptr: &read_ptr_slice[0], - pad_flags: pad_flags_slice, - padding_occurred: &padding_occurred_slice[0], - } - } - pub const fn width() -> usize { - 0 + 1 + 1 + 1 + 1 * 6 + 1 - } -} -impl<'b, T> ShaVmControlColsRef<'b, T> { - pub fn from_mut<'a, C: ShaChipConfig>(other: &'b ShaVmControlColsRefMut<'a, T>) -> Self { - Self { - len: &other.len, - cur_timestamp: &other.cur_timestamp, - read_ptr: &other.read_ptr, - pad_flags: other.pad_flags.view(), - padding_occurred: &other.padding_occurred, - } - } -} -pub struct ShaVmControlColsRefMut<'a, T> { - pub len: &'a mut T, - pub cur_timestamp: &'a mut T, - pub read_ptr: &'a mut T, - pub pad_flags: ndarray::ArrayViewMut1<'a, T>, - pub padding_occurred: &'a mut T, -} -impl<'a, T> ShaVmControlColsRefMut<'a, T> { - pub fn from(slice: &'a mut [T]) -> Self { - let len_length = 1; - let (len_slice, slice) = slice.split_at_mut(len_length); - let cur_timestamp_length = 1; - let (cur_timestamp_slice, slice) = slice.split_at_mut(cur_timestamp_length); - let read_ptr_length = 1; - let (read_ptr_slice, slice) = slice.split_at_mut(read_ptr_length); - let (pad_flags_slice, slice) = slice.split_at_mut(1 * 6); - let pad_flags_slice = ndarray::ArrayViewMut1::from_shape((6), pad_flags_slice).unwrap(); - let padding_occurred_length = 1; - let (padding_occurred_slice, slice) = slice.split_at_mut(padding_occurred_length); - Self { - len: &mut len_slice[0], - cur_timestamp: &mut cur_timestamp_slice[0], - read_ptr: &mut read_ptr_slice[0], - pad_flags: pad_flags_slice, - padding_occurred: &mut padding_occurred_slice[0], - } - } - pub const fn width() -> usize { - 0 + 1 + 1 + 1 + 1 * 6 + 1 - } -} From 12321d48af20af1f8485db6c37b502e5c542d39b Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 14:31:47 -0400 Subject: [PATCH 21/27] fix lint errors --- Cargo.toml | 1 - crates/circuits/primitives/derive/Cargo.toml | 1 - crates/circuits/primitives/derive/src/cols_ref.rs | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1a201042b1..5ace13f77a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,6 @@ 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-sha2-air = { path = "crates/circuits/sha2-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/primitives/derive/Cargo.toml b/crates/circuits/primitives/derive/Cargo.toml index cde8f40f69..f2dd038ea2 100644 --- a/crates/circuits/primitives/derive/Cargo.toml +++ b/crates/circuits/primitives/derive/Cargo.toml @@ -18,7 +18,6 @@ itertools = { workspace = true, default-features = true } proc-macro2 = "1.0" [dev-dependencies] -openvm-sha2-air = { workspace = true } ndarray.workspace = true [package.metadata.cargo-shear] diff --git a/crates/circuits/primitives/derive/src/cols_ref.rs b/crates/circuits/primitives/derive/src/cols_ref.rs index fb623af737..204db83e36 100644 --- a/crates/circuits/primitives/derive/src/cols_ref.rs +++ b/crates/circuits/primitives/derive/src/cols_ref.rs @@ -1,7 +1,6 @@ use itertools::Itertools; -use proc_macro::TokenStream; use quote::{format_ident, quote}; -use syn::{parse_macro_input, parse_quote, DeriveInput}; +use syn::{parse_quote, DeriveInput}; pub fn cols_ref_impl( derive_input: DeriveInput, From eb79f340308da9a6d9f8e4ee49ec229cccacc96a Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 17:05:06 -0400 Subject: [PATCH 22/27] Add documentation for ColsRef macro --- crates/circuits/primitives/derive/Cargo.toml | 2 +- .../primitives/derive/src/cols_ref/README.md | 112 +++++++ .../src/{cols_ref.rs => cols_ref/mod.rs} | 66 ++-- crates/circuits/primitives/derive/src/lib.rs | 4 +- .../primitives/derive/tests/example.rs | 87 +++++ .../primitives/derive/tests/test_cols_ref.rs | 298 ++++++++++++++++++ 6 files changed, 533 insertions(+), 36 deletions(-) create mode 100644 crates/circuits/primitives/derive/src/cols_ref/README.md rename crates/circuits/primitives/derive/src/{cols_ref.rs => cols_ref/mod.rs} (90%) create mode 100644 crates/circuits/primitives/derive/tests/example.rs diff --git a/crates/circuits/primitives/derive/Cargo.toml b/crates/circuits/primitives/derive/Cargo.toml index f2dd038ea2..2e91772fd5 100644 --- a/crates/circuits/primitives/derive/Cargo.toml +++ b/crates/circuits/primitives/derive/Cargo.toml @@ -12,7 +12,7 @@ license.workspace = true proc-macro = true [dependencies] -syn = { version = "2.0", features = ["parsing"] } +syn = { version = "2.0", features = ["parsing", "extra-traits"] } quote = "1.0" itertools = { workspace = true, default-features = true } proc-macro2 = "1.0" diff --git a/crates/circuits/primitives/derive/src/cols_ref/README.md b/crates/circuits/primitives/derive/src/cols_ref/README.md new file mode 100644 index 0000000000..b8eafc8659 --- /dev/null +++ b/crates/circuits/primitives/derive/src/cols_ref/README.md @@ -0,0 +1,112 @@ +# ColsRef macro + +The `ColsRef` procedural macro is used in constraint generation to create column structs that have dynamic sizes. + +Note: this macro was originally created for use in the SHA-2 VM extension, where we reuse the same constraint generation code for three different circuits (SHA-256, SHA-512, and SHA-384). +See the [SHA-2 VM extension](../../../../../../extensions/sha2/circuit/src/sha2_chip/air.rs) for an example of how to use the `ColsRef` macro to reuse constraint generation code over multiple circuits. + +## Overview + +As an illustrative example, consider the following columns struct: +```rust +struct ExampleCols { + arr: [T; N], + sum: T, +} +``` +Let's say we want to constrain `sum` to be the sum of the elements of `arr`, and `N` can be either 5 or 10. +We can define a trait that stores the config parameters. +```rust +pub trait ExampleConfig { + const N: usize; +} +``` +and then implement it for the two different configs. +```rust +pub struct ExampleConfigImplA; +impl ExampleConfig for ExampleConfigImplA { + const N: usize = 5; +} +pub struct ExampleConfigImplB; +impl ExampleConfig for ExampleConfigImplB { + const N: usize = 10; +} +``` +Then we can use the `ColsRef` macro like this +```rust +#[derive(ColsRef)] +#[config(ExampleConfig)] +struct ExampleCols { + arr: [T; N], + sum: T, +} +``` +which will generate a columns struct that uses references to the fields. +```rust +struct ExampleColsRef<'a, T, const N: usize> { + arr: &'a [T; N], + sum: &'a T, +} +``` +The `ColsRef` macro will also generate a `from` method that takes a slice of the correct length and returns an instance of the columns struct. +The `from` method is parameterized by a struct that implements the `ExampleConfig` trait, and it uses the associated constants to determine how to split the input slice into the fields of the columns struct. + +So, the constraint generation code can be written as +```rust +impl Air for ExampleAir { + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let (local, _) = (main.row_slice(0), main.row_slice(1)); + let local_cols = ExampleColsRef::::from::(&local[..C::N + 1]); + let sum = local_cols.arr.iter().sum(); + builder.assert_eq(local_cols.sum, sum); + } +} +``` +Notes: +- the `arr` and `sum` fields of `ExampleColsRef` are references to the elements of the `local` slice. +- the name, `N`, of the const generic parameter must match the name of the associated constant `N` in the `ExampleConfig` trait. + +The `ColsRef` macro also generates a `ExampleColsRefMut` struct that stores mutable references to the fields, for use in trace generation. + +The `ColsRef` macro supports more than just variable-length array fields. +The field types can also be: +- any type that derives `AlignedBorrow` via `#[derive(AlignedBorrow)]` +- any type that derives `ColsRef` via `#[derive(ColsRef)]` +- (possibly nested) arrays of `T` or (possibly nested) arrays of a type that derives `AlignedBorrow` + +Note that we currently do not support arrays of types that derive `ColsRef`. + +## Specification + +Annotating a struct named `ExampleCols` with `#[derive(ColsRef)]` and `#[config(ExampleConfig)]` produces two structs, `ExampleColsRef` and `ExampleColsRefMut`. +- we assume `ExampleCols` has exactly one generic type parameter, typically named `T`, and any number of const generic parameters. Each const generic parameter must have a name that matches an associated constant in the `ExampleConfig` trait + +The fields of `ExampleColsRef` have the same names as the fields of `ExampleCols`, but their types are transformed as follows: +- type `T` becomes `&T` +- type `[T; LEN]` becomes `&ArrayView1` (see [ndarray](https://docs.rs/ndarray/latest/ndarray/index.html)) where `LEN` is an associated constant in `ExampleConfig` + - the `ExampleColsRef::from` method will correctly infer the length of the array from the config +- fields with names that end in `Cols` are assumed to be a columns struct that derives `ColsRef` and are transformed into the appropriate `ColsRef` type recursively + - one restriction is that any nested `ColsRef` type must have the same config as the outer `ColsRef` type +- fields that are annotated with `#[aligned_borrow]` are assumed to derive `AlignedBorrow` and are borrowed from the input slice. The new type is a reference to the `AlignedBorrow` type +- nested arrays of `U` become `&ArrayViewX` where `X` is the number of dimensions in the nested array type + - `U` can be either the generic type `T` or a type that derives `AlignedBorrow`. In the latter case, the field must be annotated with `#[aligned_borrow]` + - the `ArrayViewX` type provides a `X`-dimensional view into the row slice + +The fields of `ExampleColsRefMut` are almost the same as the fields of `ExampleColsRef`, but they are mutable references. +- the `ArrayViewMutX` type is used instead of `ArrayViewX` for the array fields. +- fields that derive `ColsRef` are transformed into the appropriate `ColsRefMut` type recursively. + +Each of the `ExampleColsRef` and `ExampleColsRefMut` types has the following methods implemented: +```rust +// Takes a slice of the correct length and returns an instance of the columns struct. +pub const fn from(slice: &[T]) -> Self; +// Returns the number of cells in the struct +pub const fn width() -> usize; +``` +Note that the `width` method on both structs returns the same value. + +Additionally, the `ExampleColsRef` struct has a `from_mut` method that takes a `ExampleColsRefMut` and returns a `ExampleColsRef`. +This may be useful in trace generation to pass a `ExampleColsRefMut` to a function that expects a `ExampleColsRef`. + +See the [tests](../../tests/test_cols_ref.rs) for concrete examples of how the `ColsRef` macro handles each of the supported field types. \ No newline at end of file diff --git a/crates/circuits/primitives/derive/src/cols_ref.rs b/crates/circuits/primitives/derive/src/cols_ref/mod.rs similarity index 90% rename from crates/circuits/primitives/derive/src/cols_ref.rs rename to crates/circuits/primitives/derive/src/cols_ref/mod.rs index 204db83e36..6b4c87d747 100644 --- a/crates/circuits/primitives/derive/src/cols_ref.rs +++ b/crates/circuits/primitives/derive/src/cols_ref/mod.rs @@ -1,3 +1,5 @@ +extern crate proc_macro; + use itertools::Itertools; use quote::{format_ident, quote}; use syn::{parse_quote, DeriveInput}; @@ -36,6 +38,7 @@ pub fn cols_ref_impl( match data { syn::Data::Struct(data_struct) => { + // Process the fields of the struct, transforming the types for use in ColsRef struct let const_field_infos: Vec = data_struct .fields .iter() @@ -43,9 +46,13 @@ pub fn cols_ref_impl( .collect::, String>>() .map_err(|e| format!("Failed to process fields. {}", e))?; + // The ColsRef struct is named by appending `Ref` to the struct name let const_cols_ref_name = syn::Ident::new(&format!("{}Ref", ident), ident.span()); + + // the args to the `from` method will be different for the ColsRef and ColsRefMut structs let from_args = quote! { slice: &'a [#generic_type] }; + // Package all the necessary information to generate the ColsRef struct let struct_info = StructInfo { name: const_cols_ref_name, vis: vis.clone(), @@ -56,10 +63,13 @@ pub fn cols_ref_impl( derive_clone: true, }; + // Generate the ColsRef struct let const_cols_ref_struct = make_struct(struct_info.clone(), &config); + // Generate the `from_mut` method for the ColsRef struct let from_mut_impl = make_from_mut(struct_info, &config)?; + // Process the fields of the struct, transforming the types for use in ColsRefMut struct let mut_field_infos: Vec = data_struct .fields .iter() @@ -67,9 +77,13 @@ pub fn cols_ref_impl( .collect::, String>>() .map_err(|e| format!("Failed to process fields. {}", e))?; + // The ColsRefMut struct is named by appending `RefMut` to the struct name let mut_cols_ref_name = syn::Ident::new(&format!("{}RefMut", ident), ident.span()); + + // the args to the `from` method will be different for the ColsRef and ColsRefMut structs let from_args = quote! { slice: &'a mut [#generic_type] }; + // Package all the necessary information to generate the ColsRefMut struct let struct_info = StructInfo { name: mut_cols_ref_name, vis, @@ -80,6 +94,7 @@ pub fn cols_ref_impl( derive_clone: false, }; + // Generate the ColsRefMut struct let mut_cols_ref_struct = make_struct(struct_info, &config); Ok(quote! { @@ -103,6 +118,12 @@ struct StructInfo { derive_clone: bool, } +// Generate the ColsRef and ColsRefMut structs, depending on the value of `struct_info` +// This function is meant to reduce code duplication between the code needed to generate the two structs +// Notable differences between the two structs are: +// - the types of the fields +// - ColsRef derives Clone, but ColsRefMut cannot (since it stores mutable references) +// - the `from` method parameter is a reference to a slice for ColsRef and a mutable reference to a slice for ColsRefMut fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_macro2::TokenStream { let StructInfo { name, @@ -147,7 +168,6 @@ fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_mac } } - // TODO: make this return the size in bytes (to support fields of constant size) // returns number of cells in the struct (where each cell has type T) pub const fn width() -> usize { 0 #( + #length_exprs )* @@ -156,6 +176,7 @@ fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_mac } } +// Generate the `from_mut` method for the ColsRef struct fn make_from_mut( struct_info: StructInfo, config: &proc_macro2::Ident, @@ -183,10 +204,12 @@ fn make_from_mut( let is_array = matches!(f.ty, syn::Type::Array(_)); if is_array { + // calling view() on ArrayViewMut returns an ArrayView Ok(quote! { other.#ident.view() }) } else if derives_aligned_borrow { + // implicitly converts a mutable reference to an immutable reference, so leave the field value unchanged Ok(quote! { other.#ident }) @@ -194,10 +217,12 @@ fn make_from_mut( // 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 }); + // Recursively call `from_mut` on the ColsRef field Ok(quote! { <#cols_ref_type>::from_mut::(&other.#ident) }) } else if is_generic_type(&f.ty, &generic_type) { + // implicitly converts a mutable reference to an immutable reference, so leave the field value unchanged Ok(quote! { &other.#ident }) @@ -230,6 +255,8 @@ fn make_from_mut( }) } +// Information about a field that is used to generate the ColsRef and ColsRefMut structs +// See the `make_struct` function to see how this information is used #[derive(Debug, Clone)] struct FieldInfo { // type for struct definition @@ -257,13 +284,8 @@ fn get_const_cols_ref_fields( .iter() .any(|attr| attr.path().is_ident("aligned_borrow")); - let has_plain_array_attribute = f.attrs.iter().any(|attr| attr.path().is_ident("array")); let is_array = matches!(f.ty, syn::Type::Array(_)); - if has_plain_array_attribute && !is_array { - panic!("field marked with `plain_array` attribute must be an array"); - } - if is_array { let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); debug_assert!( @@ -286,33 +308,7 @@ fn get_const_cols_ref_fields( }) .collect_vec(); - if has_plain_array_attribute { - Err("unsupported currently".to_string()) - /* - debug_assert!( - dims.len() == 1, - "field marked with `plain_array` attribute must be a 1D array" - ); - - let length_expr = quote! { - 1 #(* #dim_exprs)* - }; - - Ok(FieldInfo { - ty: parse_quote! { - & #f.ty - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at(#length_expr); - let #slice_var = #slice_var.try_into().unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - */ - } else if derives_aligned_borrow { + if derives_aligned_borrow { let length_expr = quote! { <#elem_type>::width() #(* #dim_exprs)* }; @@ -552,6 +548,8 @@ fn get_mut_cols_ref_fields( } } +// Helper functions + fn is_columns_struct(ty: &syn::Type) -> bool { if let syn::Type::Path(type_path) = ty { type_path @@ -666,6 +664,8 @@ fn get_elem_type(ty: &syn::Type) -> syn::Type { } } +// Get a vector of the dimensions of the array +// Each dimension is either a constant generic or a literal integer value fn get_dims(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { get_dims_impl(ty, const_generics) .into_iter() diff --git a/crates/circuits/primitives/derive/src/lib.rs b/crates/circuits/primitives/derive/src/lib.rs index ced79f7f9c..c82545a67a 100644 --- a/crates/circuits/primitives/derive/src/lib.rs +++ b/crates/circuits/primitives/derive/src/lib.rs @@ -402,8 +402,8 @@ pub fn bytes_stateful_derive(input: TokenStream) -> TokenStream { } } -#[proc_macro_derive(ColsRef, attributes(aligned_borrow, config, plain_array))] -pub fn cols_ref(input: TokenStream) -> TokenStream { +#[proc_macro_derive(ColsRef, attributes(aligned_borrow, config))] +pub fn cols_ref_derive(input: TokenStream) -> TokenStream { let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput); let config = derive_input diff --git a/crates/circuits/primitives/derive/tests/example.rs b/crates/circuits/primitives/derive/tests/example.rs new file mode 100644 index 0000000000..58bac9e26c --- /dev/null +++ b/crates/circuits/primitives/derive/tests/example.rs @@ -0,0 +1,87 @@ +use openvm_circuit_primitives_derive::ColsRef; + +pub trait ExampleConfig { + const N: usize; +} +pub struct ExampleConfigImplA; +impl ExampleConfig for ExampleConfigImplA { + const N: usize = 5; +} +pub struct ExampleConfigImplB; +impl ExampleConfig for ExampleConfigImplB { + const N: usize = 10; +} + +#[allow(dead_code)] +#[derive(ColsRef)] +#[config(ExampleConfig)] +struct ExampleCols { + arr: [T; N], + sum: T, +} + +#[test] +fn example() { + let input = [1, 2, 3, 4, 5, 15]; + let test: ExampleColsRef = ExampleColsRef::from::(&input); + println!("{}, {}", test.arr, test.sum); +} + +/* + * For reference, this is what the ColsRef macro expands to. + * The `cargo expand` tool is helpful for understanding how the ColsRef macro works. + * See https://github.com/dtolnay/cargo-expand + +#[derive(Debug, Clone)] +struct ExampleColsRef<'a, T> { + pub arr: ndarray::ArrayView1<'a, T>, + pub sum: &'a T, +} + +impl<'a, T> ExampleColsRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let (arr_slice, slice) = slice.split_at(1 * C::N); + let arr_slice = ndarray::ArrayView1::from_shape((C::N), arr_slice).unwrap(); + let sum_length = 1; + let (sum_slice, slice) = slice.split_at(sum_length); + Self { + arr: arr_slice, + sum: &sum_slice[0], + } + } + pub const fn width() -> usize { + 0 + 1 * C::N + 1 + } +} + +impl<'b, T> ExampleColsRef<'b, T> { + pub fn from_mut<'a, C: ExampleConfig>(other: &'b ExampleColsRefMut<'a, T>) -> Self { + Self { + arr: other.arr.view(), + sum: &other.sum, + } + } +} + +#[derive(Debug)] +struct ExampleColsRefMut<'a, T> { + pub arr: ndarray::ArrayViewMut1<'a, T>, + pub sum: &'a mut T, +} + +impl<'a, T> ExampleColsRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let (arr_slice, slice) = slice.split_at_mut(1 * C::N); + let arr_slice = ndarray::ArrayViewMut1::from_shape((C::N), arr_slice).unwrap(); + let sum_length = 1; + let (sum_slice, slice) = slice.split_at_mut(sum_length); + Self { + arr: arr_slice, + sum: &mut sum_slice[0], + } + } + pub const fn width() -> usize { + 0 + 1 * C::N + 1 + } +} +*/ diff --git a/crates/circuits/primitives/derive/tests/test_cols_ref.rs b/crates/circuits/primitives/derive/tests/test_cols_ref.rs index 8b13789179..c76464b329 100644 --- a/crates/circuits/primitives/derive/tests/test_cols_ref.rs +++ b/crates/circuits/primitives/derive/tests/test_cols_ref.rs @@ -1 +1,299 @@ +use openvm_circuit_primitives_derive::{AlignedBorrow, ColsRef}; +pub trait TestConfig { + const N: usize; + const M: usize; +} +pub struct TestConfigImpl; +impl TestConfig for TestConfigImpl { + const N: usize = 5; + const M: usize = 2; +} + +#[allow(dead_code)] // TestCols isn't acutally used in the code. silence clippy warning +#[derive(ColsRef)] +#[config(TestConfig)] +struct TestCols { + single_field_element: T, + array_of_t: [T; N], + nested_array_of_t: [[T; N]; N], + cols_struct: TestSubCols, + #[aligned_borrow] + array_of_aligned_borrow: [TestAlignedBorrow; N], + #[aligned_borrow] + nested_array_of_aligned_borrow: [[TestAlignedBorrow; N]; N], +} + +#[allow(dead_code)] // TestSubCols isn't acutally used in the code. silence clippy warning +#[derive(ColsRef, Debug)] +#[config(TestConfig)] +struct TestSubCols { + // TestSubCols can have fields of any type that TestCols can have + a: T, + b: [T; M], + #[aligned_borrow] + c: TestAlignedBorrow, +} + +#[derive(AlignedBorrow, Debug)] +struct TestAlignedBorrow { + a: T, + b: [T; 5], +} + +#[test] +fn test_cols_ref() { + assert_eq!( + TestColsRef::::width::(), + TestColsRefMut::::width::() + ); + const WIDTH: usize = TestColsRef::::width::(); + let mut input = vec![0; WIDTH]; + let mut cols: TestColsRefMut = TestColsRefMut::from::(&mut input); + + *cols.single_field_element = 1; + cols.array_of_t[0] = 2; + cols.nested_array_of_t[[0, 0]] = 3; + *cols.cols_struct.a = 4; + cols.cols_struct.b[0] = 5; + cols.cols_struct.c.a = 6; + cols.cols_struct.c.b[0] = 7; + cols.array_of_aligned_borrow[0].a = 8; + cols.array_of_aligned_borrow[0].b[0] = 9; + cols.nested_array_of_aligned_borrow[[0, 0]].a = 10; + cols.nested_array_of_aligned_borrow[[0, 0]].b[0] = 11; + + let cols: TestColsRef = TestColsRef::from::(&input); + println!("{:?}", cols); + assert_eq!(*cols.single_field_element, 1); + assert_eq!(cols.array_of_t[0], 2); + assert_eq!(cols.nested_array_of_t[[0, 0]], 3); + assert_eq!(*cols.cols_struct.a, 4); + assert_eq!(cols.cols_struct.b[0], 5); + assert_eq!(cols.cols_struct.c.a, 6); + assert_eq!(cols.cols_struct.c.b[0], 7); + assert_eq!(cols.array_of_aligned_borrow[0].a, 8); + assert_eq!(cols.array_of_aligned_borrow[0].b[0], 9); + assert_eq!(cols.nested_array_of_aligned_borrow[[0, 0]].a, 10); + assert_eq!(cols.nested_array_of_aligned_borrow[[0, 0]].b[0], 11); +} + +/* + * For reference, this is what the ColsRef macro expands to. + * The `cargo expand` tool is helpful for understanding how the ColsRef macro works. + * See https://github.com/dtolnay/cargo-expand + +#[derive(Debug, Clone)] +struct TestColsRef<'a, T> { + pub single_field_element: &'a T, + pub array_of_t: ndarray::ArrayView1<'a, T>, + pub nested_array_of_t: ndarray::ArrayView2<'a, T>, + pub cols_struct: TestSubColsRef<'a, T>, + pub array_of_aligned_borrow: ndarray::ArrayView1<'a, TestAlignedBorrow>, + pub nested_array_of_aligned_borrow: ndarray::ArrayView2<'a, TestAlignedBorrow>, +} + +impl<'a, T> TestColsRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let single_field_element_length = 1; + let (single_field_element_slice, slice) = slice + .split_at(single_field_element_length); + let (array_of_t_slice, slice) = slice.split_at(1 * C::N); + let array_of_t_slice = ndarray::ArrayView1::from_shape((C::N), array_of_t_slice) + .unwrap(); + let (nested_array_of_t_slice, slice) = slice.split_at(1 * C::N * C::N); + let nested_array_of_t_slice = ndarray::ArrayView2::from_shape( + (C::N, C::N), + nested_array_of_t_slice, + ) + .unwrap(); + let cols_struct_length = >::width::(); + let (cols_struct_slice, slice) = slice.split_at(cols_struct_length); + let cols_struct_slice = >::from::(cols_struct_slice); + let (array_of_aligned_borrow_slice, slice) = slice + .split_at(>::width() * C::N); + let array_of_aligned_borrow_slice: &[TestAlignedBorrow] = unsafe { + &*(array_of_aligned_borrow_slice as *const [T] + as *const [TestAlignedBorrow]) + }; + let array_of_aligned_borrow_slice = ndarray::ArrayView1::from_shape( + (C::N), + array_of_aligned_borrow_slice, + ) + .unwrap(); + let (nested_array_of_aligned_borrow_slice, slice) = slice + .split_at(>::width() * C::N * C::N); + let nested_array_of_aligned_borrow_slice: &[TestAlignedBorrow] = unsafe { + &*(nested_array_of_aligned_borrow_slice as *const [T] + as *const [TestAlignedBorrow]) + }; + let nested_array_of_aligned_borrow_slice = ndarray::ArrayView2::from_shape( + (C::N, C::N), + nested_array_of_aligned_borrow_slice, + ) + .unwrap(); + Self { + single_field_element: &single_field_element_slice[0], + array_of_t: array_of_t_slice, + nested_array_of_t: nested_array_of_t_slice, + cols_struct: cols_struct_slice, + array_of_aligned_borrow: array_of_aligned_borrow_slice, + nested_array_of_aligned_borrow: nested_array_of_aligned_borrow_slice, + } + } + pub const fn width() -> usize { + 0 + 1 + 1 * C::N + 1 * C::N * C::N + >::width::() + + >::width() * C::N + + >::width() * C::N * C::N + } +} + +impl<'b, T> TestColsRef<'b, T> { + pub fn from_mut<'a, C: TestConfig>(other: &'b TestColsRefMut<'a, T>) -> Self { + Self { + single_field_element: &other.single_field_element, + array_of_t: other.array_of_t.view(), + nested_array_of_t: other.nested_array_of_t.view(), + cols_struct: >::from_mut::(&other.cols_struct), + array_of_aligned_borrow: other.array_of_aligned_borrow.view(), + nested_array_of_aligned_borrow: other.nested_array_of_aligned_borrow.view(), + } + } +} + +#[derive(Debug)] +struct TestColsRefMut<'a, T> { + pub single_field_element: &'a mut T, + pub array_of_t: ndarray::ArrayViewMut1<'a, T>, + pub nested_array_of_t: ndarray::ArrayViewMut2<'a, T>, + pub cols_struct: TestSubColsRefMut<'a, T>, + pub array_of_aligned_borrow: ndarray::ArrayViewMut1<'a, TestAlignedBorrow>, + pub nested_array_of_aligned_borrow: ndarray::ArrayViewMut2<'a, TestAlignedBorrow>, +} + +impl<'a, T> TestColsRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let single_field_element_length = 1; + let (single_field_element_slice, slice) = slice + .split_at_mut(single_field_element_length); + let (array_of_t_slice, slice) = slice.split_at_mut(1 * C::N); + let array_of_t_slice = ndarray::ArrayViewMut1::from_shape( + (C::N), + array_of_t_slice, + ) + .unwrap(); + let (nested_array_of_t_slice, slice) = slice.split_at_mut(1 * C::N * C::N); + let nested_array_of_t_slice = ndarray::ArrayViewMut2::from_shape( + (C::N, C::N), + nested_array_of_t_slice, + ) + .unwrap(); + let cols_struct_length = >::width::(); + let (cols_struct_slice, slice) = slice.split_at_mut(cols_struct_length); + let cols_struct_slice = >::from::(cols_struct_slice); + let (array_of_aligned_borrow_slice, slice) = slice + .split_at_mut(>::width() * C::N); + let array_of_aligned_borrow_slice: &mut [TestAlignedBorrow] = unsafe { + &mut *(array_of_aligned_borrow_slice as *mut [T] + as *mut [TestAlignedBorrow]) + }; + let array_of_aligned_borrow_slice = ndarray::ArrayViewMut1::from_shape( + (C::N), + array_of_aligned_borrow_slice, + ) + .unwrap(); + let (nested_array_of_aligned_borrow_slice, slice) = slice + .split_at_mut(>::width() * C::N * C::N); + let nested_array_of_aligned_borrow_slice: &mut [TestAlignedBorrow] = unsafe { + &mut *(nested_array_of_aligned_borrow_slice as *mut [T] + as *mut [TestAlignedBorrow]) + }; + let nested_array_of_aligned_borrow_slice = ndarray::ArrayViewMut2::from_shape( + (C::N, C::N), + nested_array_of_aligned_borrow_slice, + ) + .unwrap(); + Self { + single_field_element: &mut single_field_element_slice[0], + array_of_t: array_of_t_slice, + nested_array_of_t: nested_array_of_t_slice, + cols_struct: cols_struct_slice, + array_of_aligned_borrow: array_of_aligned_borrow_slice, + nested_array_of_aligned_borrow: nested_array_of_aligned_borrow_slice, + } + } + pub const fn width() -> usize { + 0 + 1 + 1 * C::N + 1 * C::N * C::N + >::width::() + + >::width() * C::N + + >::width() * C::N * C::N + } +} + +#[derive(Debug, Clone)] +struct TestSubColsRef<'a, T> { + pub a: &'a T, + pub b: ndarray::ArrayView1<'a, T>, + pub c: &'a TestAlignedBorrow, +} + +impl<'a, T> TestSubColsRef<'a, T> { + pub fn from(slice: &'a [T]) -> Self { + let a_length = 1; + let (a_slice, slice) = slice.split_at(a_length); + let (b_slice, slice) = slice.split_at(1 * C::M); + let b_slice = ndarray::ArrayView1::from_shape((C::M), b_slice).unwrap(); + let c_length = >::width(); + let (c_slice, slice) = slice.split_at(c_length); + Self { + a: &a_slice[0], + b: b_slice, + c: { + use core::borrow::Borrow; + c_slice.borrow() + }, + } + } + pub const fn width() -> usize { + 0 + 1 + 1 * C::M + >::width() + } +} + +impl<'b, T> TestSubColsRef<'b, T> { + pub fn from_mut<'a, C: TestConfig>(other: &'b TestSubColsRefMut<'a, T>) -> Self { + Self { + a: &other.a, + b: other.b.view(), + c: other.c, + } + } +} + +#[derive(Debug)] +struct TestSubColsRefMut<'a, T> { + pub a: &'a mut T, + pub b: ndarray::ArrayViewMut1<'a, T>, + pub c: &'a mut TestAlignedBorrow, +} + +impl<'a, T> TestSubColsRefMut<'a, T> { + pub fn from(slice: &'a mut [T]) -> Self { + let a_length = 1; + let (a_slice, slice) = slice.split_at_mut(a_length); + let (b_slice, slice) = slice.split_at_mut(1 * C::M); + let b_slice = ndarray::ArrayViewMut1::from_shape((C::M), b_slice).unwrap(); + let c_length = >::width(); + let (c_slice, slice) = slice.split_at_mut(c_length); + Self { + a: &mut a_slice[0], + b: b_slice, + c: { + use core::borrow::BorrowMut; + c_slice.borrow_mut() + }, + } + } + pub const fn width() -> usize { + 0 + 1 + 1 * C::M + >::width() + } +} +*/ From 64b0aaadd83539922ccd2560003bb28d0baeacf9 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 17:24:38 -0400 Subject: [PATCH 23/27] lint errors --- crates/circuits/primitives/derive/tests/test_cols_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/circuits/primitives/derive/tests/test_cols_ref.rs b/crates/circuits/primitives/derive/tests/test_cols_ref.rs index c76464b329..6bad0c4f9f 100644 --- a/crates/circuits/primitives/derive/tests/test_cols_ref.rs +++ b/crates/circuits/primitives/derive/tests/test_cols_ref.rs @@ -10,7 +10,7 @@ impl TestConfig for TestConfigImpl { const M: usize = 2; } -#[allow(dead_code)] // TestCols isn't acutally used in the code. silence clippy warning +#[allow(dead_code)] // TestCols isn't actually used in the code. silence clippy warning #[derive(ColsRef)] #[config(TestConfig)] struct TestCols { @@ -24,7 +24,7 @@ struct TestCols { nested_array_of_aligned_borrow: [[TestAlignedBorrow; N]; N], } -#[allow(dead_code)] // TestSubCols isn't acutally used in the code. silence clippy warning +#[allow(dead_code)] // TestSubCols isn't actually used in the code. silence clippy warning #[derive(ColsRef, Debug)] #[config(TestConfig)] struct TestSubCols { From 4e2dcdfec0cf4b430827d28a8a0df25c8928e5ce Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 17:39:29 -0400 Subject: [PATCH 24/27] Remove old sha macro crate --- crates/circuits/cols-ref-macro/Cargo.toml | 24 - crates/circuits/cols-ref-macro/src/lib.rs | 730 ------------------ .../cols-ref-macro/tests/aligned_borrow.rs | 54 -- .../circuits/cols-ref-macro/tests/arrays.rs | 84 -- .../cols-ref-macro/tests/const-len-arrays.rs | 28 - crates/circuits/cols-ref-macro/tests/flags.rs | 36 - .../circuits/cols-ref-macro/tests/nested.rs | 45 -- .../circuits/cols-ref-macro/tests/simple.rs | 19 - .../cols-ref-macro/tests/test_config.rs | 7 - .../cols-ref-macro/tests/work-vars.rs | 29 - 10 files changed, 1056 deletions(-) delete mode 100644 crates/circuits/cols-ref-macro/Cargo.toml delete mode 100644 crates/circuits/cols-ref-macro/src/lib.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/aligned_borrow.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/arrays.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/const-len-arrays.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/flags.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/nested.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/simple.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/test_config.rs delete mode 100644 crates/circuits/cols-ref-macro/tests/work-vars.rs diff --git a/crates/circuits/cols-ref-macro/Cargo.toml b/crates/circuits/cols-ref-macro/Cargo.toml deleted file mode 100644 index 8bf47baad2..0000000000 --- a/crates/circuits/cols-ref-macro/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "todo-delete" -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" -itertools = "0.14" -proc-macro2 = "1.0" - -[dev-dependencies] -openvm-sha2-air = { workspace = true } -openvm-circuit-primitives-derive = { workspace = true } -ndarray.workspace = true - -[lib] -proc-macro = true - -[package.metadata.cargo-shear] -ignored = ["ndarray"] \ No newline at end of file diff --git a/crates/circuits/cols-ref-macro/src/lib.rs b/crates/circuits/cols-ref-macro/src/lib.rs deleted file mode 100644 index 7d59b42cfe..0000000000 --- a/crates/circuits/cols-ref-macro/src/lib.rs +++ /dev/null @@ -1,730 +0,0 @@ -extern crate proc_macro; - -use itertools::Itertools; -use proc_macro::TokenStream; -use quote::{format_ident, quote}; -use syn::{parse_macro_input, parse_quote, DeriveInput}; - -#[proc_macro_derive(ColsRef, attributes(aligned_borrow, config, plain_array))] -pub fn cols_ref(input: TokenStream) -> TokenStream { - let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput); - - let config = derive_input - .attrs - .iter() - .find(|attr| attr.path().is_ident("config")); - if config.is_none() { - return syn::Error::new(derive_input.ident.span(), "Config attribute is required") - .to_compile_error() - .into(); - } - let config: proc_macro2::Ident = config - .unwrap() - .parse_args() - .expect("Failed to parse config"); - - let span = derive_input.ident.span(); - let res = cols_ref_impl(derive_input, config); - res.map_or_else( - |err| { - syn::Error::new(span, err.to_string()) - .to_compile_error() - .into() - }, - |ok| ok.into(), - ) -} - -fn cols_ref_impl( - derive_input: DeriveInput, - config: proc_macro2::Ident, -) -> 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]; - - let const_generics = generics.const_params().map(|p| &p.ident).collect_vec(); - - 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, &const_generics)) - .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(), &config); - - let from_mut_impl = make_from_mut(struct_info, &config)?; - - let mut_field_infos: Vec = data_struct - .fields - .iter() - .map(|f| get_mut_cols_ref_fields(f, generic_type, &const_generics)) - .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, &config); - - 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, config: &proc_macro2::Ident) -> 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 - #[derive(Debug)] - #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 ),* - } - } - - // TODO: make this return the size in bytes (to support fields of constant size) - // returns number of cells in the struct (where each cell has type T) - pub const fn width() -> usize { - 0 #( + #length_exprs )* - } - } - } -} - -fn make_from_mut( - struct_info: StructInfo, - config: &proc_macro2::Ident, -) -> Result { - let StructInfo { - name, - vis: _, - generic_type, - field_infos: _, - fields, - from_args: _, - derive_clone: _, - } = struct_info; - - let from_mut_impl = fields - .iter() - .map(|f| { - let ident = f.ident.clone().unwrap(); - - let derives_aligned_borrow = f - .attrs - .iter() - .any(|attr| attr.path().is_ident("aligned_borrow")); - - let is_array = matches!(f.ty, syn::Type::Array(_)); - - if is_array { - Ok(quote! { - other.#ident.view() - }) - } else if derives_aligned_borrow { - Ok(quote! { - other.#ident - }) - } else if is_columns_struct(&f.ty) { - // 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 if is_generic_type(&f.ty, &generic_type) { - Ok(quote! { - &other.#ident - }) - } else { - panic!("Unsupported field 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! { - // lifetime 'b is used in from_mut to allow more flexible lifetime of return value - impl<'b, #generic_type> #name<'b, #generic_type> { - pub fn from_mut<'a, C: #config>(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, - const_generics: &[&syn::Ident], -) -> Result { - let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); - let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); - - let derives_aligned_borrow = f - .attrs - .iter() - .any(|attr| attr.path().is_ident("aligned_borrow")); - - let has_plain_array_attribute = f.attrs.iter().any(|attr| attr.path().is_ident("array")); - let is_array = matches!(f.ty, syn::Type::Array(_)); - - if has_plain_array_attribute && !is_array { - panic!("field marked with `plain_array` attribute must be an array"); - } - - if is_array { - let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); - debug_assert!( - !dims.is_empty(), - "Array field must have at least one dimension" - ); - - let ndarray_ident: syn::Ident = format_ident!("ArrayView{}", dims.len()); - let ndarray_type: syn::Type = parse_quote! { - ndarray::#ndarray_ident<'a, #elem_type> - }; - - // dimensions of the array in terms of number of cells - let dim_exprs = dims - .iter() - .map(|d| match d { - // need to prepend C:: for const generic array dimensions - Dimension::ConstGeneric(expr) => quote! { C::#expr }, - Dimension::Other(expr) => quote! { #expr }, - }) - .collect_vec(); - - if has_plain_array_attribute { - Err("unsupported currently".to_string()) - /* - debug_assert!( - dims.len() == 1, - "field marked with `plain_array` attribute must be a 1D array" - ); - - let length_expr = quote! { - 1 #(* #dim_exprs)* - }; - - Ok(FieldInfo { - ty: parse_quote! { - & #f.ty - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at(#length_expr); - let #slice_var = #slice_var.try_into().unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - */ - } else if derives_aligned_borrow { - let length_expr = quote! { - <#elem_type>::width() #(* #dim_exprs)* - }; - - Ok(FieldInfo { - ty: parse_quote! { - #ndarray_type - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at(#length_expr); - let #slice_var: &[#elem_type] = unsafe { &*(#slice_var as *const [T] as *const [#elem_type]) }; - let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - } else if is_columns_struct(&elem_type) { - panic!("Arrays of columns structs are currently not supported"); - } else if is_generic_type(&elem_type, generic_type) { - let length_expr = quote! { - 1 #(* #dim_exprs)* - }; - Ok(FieldInfo { - ty: parse_quote! { - #ndarray_type - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at(#length_expr); - let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - } else { - panic!("Unsupported field type: {:?}", f.ty); - } - } else if derives_aligned_borrow { - // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) - let f_ty = &f.ty; - Ok(FieldInfo { - ty: parse_quote! { - &'a #f_ty - }, - length_expr: quote! { - <#f_ty>::width() - }, - prepare_subslice: quote! { - let #length_var = <#f_ty>::width(); - let (#slice_var, slice) = slice.split_at(#length_var); - }, - initializer: quote! { - { - use core::borrow::Borrow; - #slice_var.borrow() - } - }, - }) - } else if is_columns_struct(&f.ty) { - let const_cols_ref_type = get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }); - Ok(FieldInfo { - ty: parse_quote! { - #const_cols_ref_type - }, - length_expr: quote! { - <#const_cols_ref_type>::width::() - }, - prepare_subslice: quote! { - let #length_var = <#const_cols_ref_type>::width::(); - let (#slice_var, slice) = slice.split_at(#length_var); - let #slice_var = <#const_cols_ref_type>::from::(#slice_var); - }, - initializer: quote! { - #slice_var - }, - }) - } else if is_generic_type(&f.ty, generic_type) { - 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 { - panic!("Unsupported field type: {:?}", f.ty); - } -} - -// Prepare the fields for the mut ColsRef struct -fn get_mut_cols_ref_fields( - f: &syn::Field, - generic_type: &syn::TypeParam, - const_generics: &[&syn::Ident], -) -> Result { - let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); - let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); - - let derives_aligned_borrow = f - .attrs - .iter() - .any(|attr| attr.path().is_ident("aligned_borrow")); - - let is_array = matches!(f.ty, syn::Type::Array(_)); - - if is_array { - let ArrayInfo { dims, elem_type } = get_array_info(&f.ty, const_generics); - debug_assert!( - !dims.is_empty(), - "Array field must have at least one dimension" - ); - - let ndarray_ident: syn::Ident = format_ident!("ArrayViewMut{}", dims.len()); - let ndarray_type: syn::Type = parse_quote! { - ndarray::#ndarray_ident<'a, #elem_type> - }; - - // dimensions of the array in terms of number of cells - let dim_exprs = dims - .iter() - .map(|d| match d { - // need to prepend C:: for const generic array dimensions - Dimension::ConstGeneric(expr) => quote! { C::#expr }, - Dimension::Other(expr) => quote! { #expr }, - }) - .collect_vec(); - - if derives_aligned_borrow { - let length_expr = quote! { - <#elem_type>::width() #(* #dim_exprs)* - }; - - Ok(FieldInfo { - ty: parse_quote! { - #ndarray_type - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at_mut (#length_expr); - let #slice_var: &mut [#elem_type] = unsafe { &mut *(#slice_var as *mut [T] as *mut [#elem_type]) }; - let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - } else if is_columns_struct(&elem_type) { - panic!("Arrays of columns structs are currently not supported"); - } else if is_generic_type(&elem_type, generic_type) { - let length_expr = quote! { - 1 #(* #dim_exprs)* - }; - Ok(FieldInfo { - ty: parse_quote! { - #ndarray_type - }, - length_expr: length_expr.clone(), - prepare_subslice: quote! { - let (#slice_var, slice) = slice.split_at_mut(#length_expr); - let #slice_var = ndarray::#ndarray_ident::from_shape( ( #(#dim_exprs),* ) , #slice_var).unwrap(); - }, - initializer: quote! { - #slice_var - }, - }) - } else { - panic!("Unsupported field type: {:?}", f.ty); - } - } else if derives_aligned_borrow { - // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) - let f_ty = &f.ty; - Ok(FieldInfo { - ty: parse_quote! { - &'a mut #f_ty - }, - length_expr: quote! { - <#f_ty>::width() - }, - prepare_subslice: quote! { - let #length_var = <#f_ty>::width(); - let (#slice_var, slice) = slice.split_at_mut(#length_var); - }, - initializer: quote! { - { - use core::borrow::BorrowMut; - #slice_var.borrow_mut() - } - }, - }) - } else if is_columns_struct(&f.ty) { - let mut_cols_ref_type = get_mut_cols_ref_type(&f.ty, generic_type); - Ok(FieldInfo { - ty: parse_quote! { - #mut_cols_ref_type - }, - length_expr: quote! { - <#mut_cols_ref_type>::width::() - }, - prepare_subslice: quote! { - let #length_var = <#mut_cols_ref_type>::width::(); - let (#slice_var, slice) = slice.split_at_mut(#length_var); - let #slice_var = <#mut_cols_ref_type>::from::(#slice_var); - }, - initializer: quote! { - #slice_var - }, - }) - } else if is_generic_type(&f.ty, generic_type) { - Ok(FieldInfo { - ty: parse_quote! { - &'a mut #generic_type - }, - length_expr: quote! { - 1 - }, - prepare_subslice: quote! { - let #length_var = 1; - let (#slice_var, slice) = slice.split_at_mut(#length_var); - }, - initializer: quote! { - &mut #slice_var[0] - }, - }) - } else { - panic!("Unsupported field type: {:?}", f.ty); - } -} - -fn is_columns_struct(ty: &syn::Type) -> bool { - if let syn::Type::Path(type_path) = ty { - type_path - .path - .segments - .iter() - .last() - .map(|s| s.ident.to_string().ends_with("Cols")) - .unwrap_or(false) - } else { - false - } -} - -// 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, -) -> syn::TypePath { - if !is_columns_struct(ty) { - panic!("Expected a columns struct, got {:?}", ty); - } - - if let syn::Type::Path(type_path) = ty { - let s = type_path.path.segments.iter().last().unwrap(); - 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> - }; - const_cols_ref_type - } else { - panic!("is_columns_struct returned true for type {:?} but the last segment is not a columns struct", ty); - } - } else { - panic!( - "is_columns_struct returned true but the type {:?} is not a path", - ty - ); - } -} - -// 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) -> syn::TypePath { - if !is_columns_struct(ty) { - panic!("Expected a columns struct, got {:?}", ty); - } - - if let syn::Type::Path(type_path) = ty { - let s = type_path.path.segments.iter().last().unwrap(); - 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> - }; - mut_cols_ref_type - } else { - panic!("is_columns_struct returned true for type {:?} but the last segment is not a columns struct", ty); - } - } else { - panic!( - "is_columns_struct returned true but the type {:?} is not a path", - ty - ); - } -} - -fn is_generic_type(ty: &syn::Type, generic_type: &syn::TypeParam) -> bool { - if let syn::Type::Path(type_path) = ty { - if type_path.path.segments.len() == 1 { - type_path - .path - .segments - .iter() - .last() - .map(|s| s.ident == generic_type.ident) - .unwrap_or(false) - } else { - false - } - } else { - false - } -} - -// Type of array dimension -enum Dimension { - ConstGeneric(syn::Expr), - Other(syn::Expr), -} - -// Describes a nested array -struct ArrayInfo { - dims: Vec, - elem_type: syn::Type, -} - -fn get_array_info(ty: &syn::Type, const_generics: &[&syn::Ident]) -> ArrayInfo { - let dims = get_dims(ty, const_generics); - let elem_type = get_elem_type(ty); - ArrayInfo { dims, elem_type } -} - -fn get_elem_type(ty: &syn::Type) -> syn::Type { - match ty { - syn::Type::Array(array) => get_elem_type(array.elem.as_ref()), - syn::Type::Path(_) => ty.clone(), - _ => panic!("Unsupported type: {:?}", ty), - } -} - -fn get_dims(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { - get_dims_impl(ty, const_generics) - .into_iter() - .rev() - .collect() -} - -fn get_dims_impl(ty: &syn::Type, const_generics: &[&syn::Ident]) -> Vec { - match ty { - syn::Type::Array(array) => { - let mut dims = get_dims_impl(array.elem.as_ref(), const_generics); - match &array.len { - syn::Expr::Path(syn::ExprPath { path, .. }) => { - let len_ident = path.get_ident(); - if len_ident.is_some() && const_generics.contains(&len_ident.unwrap()) { - dims.push(Dimension::ConstGeneric(array.len.clone())); - } else { - dims.push(Dimension::Other(array.len.clone())); - } - } - syn::Expr::Lit(expr_lit) => dims.push(Dimension::Other(expr_lit.clone().into())), - _ => panic!("Unsupported array length type"), - } - dims - } - syn::Type::Path(_) => Vec::new(), - _ => panic!("Unsupported field type"), - } -} diff --git a/crates/circuits/cols-ref-macro/tests/aligned_borrow.rs b/crates/circuits/cols-ref-macro/tests/aligned_borrow.rs deleted file mode 100644 index 3dc51112f2..0000000000 --- a/crates/circuits/cols-ref-macro/tests/aligned_borrow.rs +++ /dev/null @@ -1,54 +0,0 @@ -use openvm_circuit_primitives_derive::AlignedBorrow; -use openvm_sha_macros::ColsRef; - -mod test_config; -use test_config::{TestConfig, TestConfigImpl}; - -#[allow(dead_code)] -#[derive(ColsRef)] -#[config(TestConfig)] -struct TestCols { - a: [T; N], - // Forces the field to be treated as a struct that derives AlignedBorrow. - // In particular, ignores the fact that it ends with `Cols` and doesn't - // expect a `AlignedBorrowColsRef` type. - #[aligned_borrow] - b: AlignedBorrowCols, -} - -#[derive(Clone, Copy, Debug, AlignedBorrow)] -struct AlignedBorrowCols { - a: T, - b: [T; 4], -} - -#[test] -fn plain() { - let input = [1; TestConfigImpl::N + 1 + 4]; - let test: TestColsRef = TestColsRef::from::(&input); - println!("{}", test.a); - println!("{:?}", test.b); -} - -#[test] -fn plain_mut() { - let mut input = [1; TestConfigImpl::N + 1 + 4]; - let mut test: TestColsRefMut = TestColsRefMut::from::(&mut input); - test.a[0] = 1; - test.b.a = 1; - test.b.b[0] = 1; - println!("{}", test.a); - println!("{:?}", test.b); -} - -#[test] -fn plain_from_mut() { - let mut input = [1; TestConfigImpl::N + 1 + 4]; - let mut test: TestColsRefMut = TestColsRefMut::from::(&mut input); - test.a[0] = 1; - test.b.a = 1; - test.b.b[0] = 1; - let test2: TestColsRef = TestColsRef::from_mut::(&test); - println!("{}", test2.a); - println!("{:?}", test2.b); -} diff --git a/crates/circuits/cols-ref-macro/tests/arrays.rs b/crates/circuits/cols-ref-macro/tests/arrays.rs deleted file mode 100644 index e49f67bb69..0000000000 --- a/crates/circuits/cols-ref-macro/tests/arrays.rs +++ /dev/null @@ -1,84 +0,0 @@ -use openvm_sha_macros::ColsRef; - -mod test_config; -use test_config::{TestConfig, TestConfigImpl}; - -#[allow(dead_code)] -#[derive(ColsRef)] -#[config(TestConfig)] -struct ArrayTest { - a: T, - b: [T; N], - c: [[T; 4]; N], -} - -#[test] -fn arrays() { - let input = [1; 1 + TestConfigImpl::N + 4 * TestConfigImpl::N]; - let test: ArrayTestRef = ArrayTestRef::from::(&input); - println!("{}", test.a); - println!("{:?}", test.b); - println!("{:?}", test.c); -} - -/* -#[derive(Clone)] -struct ArrayTestRef<'a, T> { - pub a: &'a T, - pub b: ndarray::ArrayView1<'a, T>, - pub c: ndarray::ArrayView2<'a, T>, -} - -impl<'a, T> ArrayTestRef<'a, T> { - pub fn from(slice: &'a [T]) -> Self { - let a_length = 1; - let (a_slice, slice) = slice.split_at(a_length); - let (b_slice, slice) = slice.split_at(1 * C::N); - let b_slice = ndarray::ArrayView1::from_shape((C::N), b_slice).unwrap(); - let (c_slice, slice) = slice.split_at(1 * C::N * 4); - let c_slice = ndarray::ArrayView2::from_shape((C::N, 4), c_slice).unwrap(); - Self { - a: &a_slice[0], - b: b_slice, - c: c_slice, - } - } - pub const fn width() -> usize { - 0 + 1 + 1 * C::N + 1 * C::N * 4 - } -} - -impl<'b, T> ArrayTestRef<'b, T> { - pub fn from_mut<'a, C: TestConfig>(other: &'b ArrayTestRefMut<'a, T>) -> Self { - Self { - a: &other.a, - b: other.b.view(), - c: other.c.view(), - } - } -} -struct ArrayTestRefMut<'a, T> { - pub a: &'a mut T, - pub b: ndarray::ArrayViewMut1<'a, T>, - pub c: ndarray::ArrayViewMut2<'a, T>, -} - -impl<'a, T> ArrayTestRefMut<'a, T> { - pub fn from(slice: &'a mut [T]) -> Self { - let a_length = 1; - let (mut a_slice, mut slice) = slice.split_at_mut(a_length); - let (mut b_slice, mut slice) = slice.split_at_mut(1 * C::N); - let b_slice = ndarray::ArrayViewMut1::from_shape((C::N), b_slice).unwrap(); - let (mut c_slice, mut slice) = slice.split_at_mut(1 * C::N * 4); - let c_slice = ndarray::ArrayViewMut2::from_shape((C::N, 4), c_slice).unwrap(); - Self { - a: &mut a_slice[0], - b: b_slice, - c: c_slice, - } - } - pub const fn width() -> usize { - 0 + 1 + 1 * C::N + 1 * C::N * 4 - } -} -*/ diff --git a/crates/circuits/cols-ref-macro/tests/const-len-arrays.rs b/crates/circuits/cols-ref-macro/tests/const-len-arrays.rs deleted file mode 100644 index df7214a5ec..0000000000 --- a/crates/circuits/cols-ref-macro/tests/const-len-arrays.rs +++ /dev/null @@ -1,28 +0,0 @@ -use openvm_sha_macros::ColsRef; - -const ONE: usize = 1; -const TWO: usize = 2; -const THREE: usize = 3; - -mod test_config; -use test_config::{TestConfig, TestConfigImpl}; - -#[allow(dead_code)] -#[derive(ColsRef)] -#[config(TestConfig)] -struct ConstLenArrayTest { - a: T, - b: [T; N], - c: [[T; ONE]; TWO], - d: [[[T; ONE]; TWO]; THREE], -} - -#[test] -fn const_len_arrays() { - let input = [1; 1 + TestConfigImpl::N * 2 + 2 * 3]; - let test: ConstLenArrayTestRef = ConstLenArrayTestRef::from::(&input); - println!("{}", test.a); - println!("{}", test.b); - println!("{}", test.c); - println!("{}", test.d); -} diff --git a/crates/circuits/cols-ref-macro/tests/flags.rs b/crates/circuits/cols-ref-macro/tests/flags.rs deleted file mode 100644 index a370cbd53c..0000000000 --- a/crates/circuits/cols-ref-macro/tests/flags.rs +++ /dev/null @@ -1,36 +0,0 @@ -use openvm_sha2_air::{Sha256Config, Sha2Config}; -use openvm_sha_macros::ColsRef; - -#[repr(C)] -#[derive(Clone, Copy, Debug, ColsRef)] -#[config(Sha2Config)] -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/cols-ref-macro/tests/nested.rs b/crates/circuits/cols-ref-macro/tests/nested.rs deleted file mode 100644 index d4691f0265..0000000000 --- a/crates/circuits/cols-ref-macro/tests/nested.rs +++ /dev/null @@ -1,45 +0,0 @@ -use openvm_sha2_air::{Sha256Config, Sha2Config}; -use openvm_sha_macros::ColsRef; - -#[allow(dead_code)] -#[derive(ColsRef)] -#[config(Sha2Config)] -struct Test1Cols { - pub a: T, - pub nested: Test2Cols, -} - -#[allow(dead_code)] -#[derive(ColsRef)] -#[config(Sha2Config)] -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_test: Test1ColsRefMut = Test1ColsRefMut::from::(&mut mut_input); - let const_test: Test1ColsRef = Test1ColsRef::from_mut::(&mut_test); - println!( - "{}, {}, {}", - const_test.a, const_test.nested.b, const_test.nested.c - ); -} diff --git a/crates/circuits/cols-ref-macro/tests/simple.rs b/crates/circuits/cols-ref-macro/tests/simple.rs deleted file mode 100644 index 1b936720d9..0000000000 --- a/crates/circuits/cols-ref-macro/tests/simple.rs +++ /dev/null @@ -1,19 +0,0 @@ -use openvm_sha2_air::{Sha256Config, Sha2Config}; -use openvm_sha_macros::ColsRef; - -#[allow(dead_code)] -#[derive(ColsRef)] -#[config(Sha2Config)] -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/cols-ref-macro/tests/test_config.rs b/crates/circuits/cols-ref-macro/tests/test_config.rs deleted file mode 100644 index aa3b592cbb..0000000000 --- a/crates/circuits/cols-ref-macro/tests/test_config.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub trait TestConfig { - const N: usize; -} -pub struct TestConfigImpl; -impl TestConfig for TestConfigImpl { - const N: usize = 4; -} diff --git a/crates/circuits/cols-ref-macro/tests/work-vars.rs b/crates/circuits/cols-ref-macro/tests/work-vars.rs deleted file mode 100644 index 465e8de9a4..0000000000 --- a/crates/circuits/cols-ref-macro/tests/work-vars.rs +++ /dev/null @@ -1,29 +0,0 @@ -use openvm_sha2_air::{Sha256Config, Sha2Config}; -use openvm_sha_macros::ColsRef; - -#[repr(C)] -#[derive(Clone, Copy, Debug, ColsRef)] -#[config(Sha2Config)] -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 - ); -} From 41d90d73f8c6918801eb37bf94a3e0e8048f18e5 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 17:44:43 -0400 Subject: [PATCH 25/27] Fix ColsRef macro spec --- crates/circuits/primitives/derive/src/cols_ref/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/circuits/primitives/derive/src/cols_ref/README.md b/crates/circuits/primitives/derive/src/cols_ref/README.md index b8eafc8659..82812f7b90 100644 --- a/crates/circuits/primitives/derive/src/cols_ref/README.md +++ b/crates/circuits/primitives/derive/src/cols_ref/README.md @@ -44,7 +44,7 @@ struct ExampleCols { which will generate a columns struct that uses references to the fields. ```rust struct ExampleColsRef<'a, T, const N: usize> { - arr: &'a [T; N], + arr: ndarray::ArrayView1<'a, T>, // an n-dimensional view into the input slice (ArrayView2 for 2D arrays, etc.) sum: &'a T, } ``` @@ -89,6 +89,7 @@ The fields of `ExampleColsRef` have the same names as the fields of `ExampleCols - fields with names that end in `Cols` are assumed to be a columns struct that derives `ColsRef` and are transformed into the appropriate `ColsRef` type recursively - one restriction is that any nested `ColsRef` type must have the same config as the outer `ColsRef` type - fields that are annotated with `#[aligned_borrow]` are assumed to derive `AlignedBorrow` and are borrowed from the input slice. The new type is a reference to the `AlignedBorrow` type + - if a field whose name ends in `Cols` is annotated with `#[aligned_borrow]`, then the aligned borrow takes precedence, and the field is not transformed into an `ArrayView` - nested arrays of `U` become `&ArrayViewX` where `X` is the number of dimensions in the nested array type - `U` can be either the generic type `T` or a type that derives `AlignedBorrow`. In the latter case, the field must be annotated with `#[aligned_borrow]` - the `ArrayViewX` type provides a `X`-dimensional view into the row slice From 1bab7bf54e23d57c81ab146006193c14c51385d4 Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 17:56:28 -0400 Subject: [PATCH 26/27] Replace compile errors with panic in ColsRef macro --- .../primitives/derive/src/cols_ref/mod.rs | 89 +++++++++---------- crates/circuits/primitives/derive/src/lib.rs | 10 +-- 2 files changed, 43 insertions(+), 56 deletions(-) diff --git a/crates/circuits/primitives/derive/src/cols_ref/mod.rs b/crates/circuits/primitives/derive/src/cols_ref/mod.rs index 6b4c87d747..f4a772b423 100644 --- a/crates/circuits/primitives/derive/src/cols_ref/mod.rs +++ b/crates/circuits/primitives/derive/src/cols_ref/mod.rs @@ -7,7 +7,7 @@ use syn::{parse_quote, DeriveInput}; pub fn cols_ref_impl( derive_input: DeriveInput, config: proc_macro2::Ident, -) -> Result { +) -> proc_macro2::TokenStream { let DeriveInput { ident, generics, @@ -29,7 +29,7 @@ pub fn cols_ref_impl( .collect::>(); if generic_types.len() != 1 { - return Err("Struct must have exactly one generic type parameter".to_string()); + panic!("Struct must have exactly one generic type parameter"); } let generic_type = generic_types[0]; @@ -43,8 +43,7 @@ pub fn cols_ref_impl( .fields .iter() .map(|f| get_const_cols_ref_fields(f, generic_type, &const_generics)) - .collect::, String>>() - .map_err(|e| format!("Failed to process fields. {}", e))?; + .collect_vec(); // The ColsRef struct is named by appending `Ref` to the struct name let const_cols_ref_name = syn::Ident::new(&format!("{}Ref", ident), ident.span()); @@ -67,15 +66,14 @@ pub fn cols_ref_impl( let const_cols_ref_struct = make_struct(struct_info.clone(), &config); // Generate the `from_mut` method for the ColsRef struct - let from_mut_impl = make_from_mut(struct_info, &config)?; + let from_mut_impl = make_from_mut(struct_info, &config); // Process the fields of the struct, transforming the types for use in ColsRefMut struct let mut_field_infos: Vec = data_struct .fields .iter() .map(|f| get_mut_cols_ref_fields(f, generic_type, &const_generics)) - .collect::, String>>() - .map_err(|e| format!("Failed to process fields. {}", e))?; + .collect_vec(); // The ColsRefMut struct is named by appending `RefMut` to the struct name let mut_cols_ref_name = syn::Ident::new(&format!("{}RefMut", ident), ident.span()); @@ -97,13 +95,13 @@ pub fn cols_ref_impl( // Generate the ColsRefMut struct let mut_cols_ref_struct = make_struct(struct_info, &config); - Ok(quote! { + quote! { #const_cols_ref_struct #from_mut_impl #mut_cols_ref_struct - }) + } } - _ => Err("ColsRef can only be derived for structs".to_string()), + _ => panic!("ColsRef can only be derived for structs"), } } @@ -177,10 +175,7 @@ fn make_struct(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_mac } // Generate the `from_mut` method for the ColsRef struct -fn make_from_mut( - struct_info: StructInfo, - config: &proc_macro2::Ident, -) -> Result { +fn make_from_mut(struct_info: StructInfo, config: &proc_macro2::Ident) -> proc_macro2::TokenStream { let StructInfo { name, vis: _, @@ -205,32 +200,32 @@ fn make_from_mut( if is_array { // calling view() on ArrayViewMut returns an ArrayView - Ok(quote! { + quote! { other.#ident.view() - }) + } } else if derives_aligned_borrow { // implicitly converts a mutable reference to an immutable reference, so leave the field value unchanged - Ok(quote! { + quote! { other.#ident - }) + } } else if is_columns_struct(&f.ty) { // 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 }); // Recursively call `from_mut` on the ColsRef field - Ok(quote! { + quote! { <#cols_ref_type>::from_mut::(&other.#ident) - }) + } } else if is_generic_type(&f.ty, &generic_type) { // implicitly converts a mutable reference to an immutable reference, so leave the field value unchanged - Ok(quote! { + quote! { &other.#ident - }) + } } else { panic!("Unsupported field type: {:?}", f.ty); } }) - .collect::, String>>()?; + .collect_vec(); let field_idents = fields .iter() @@ -242,7 +237,7 @@ fn make_from_mut( #mut_struct_ident<'a, #generic_type> }; - Ok(parse_quote! { + parse_quote! { // lifetime 'b is used in from_mut to allow more flexible lifetime of return value impl<'b, #generic_type> #name<'b, #generic_type> { pub fn from_mut<'a, C: #config>(other: &'b #mut_struct_type) -> Self @@ -252,7 +247,7 @@ fn make_from_mut( } } } - }) + } } // Information about a field that is used to generate the ColsRef and ColsRefMut structs @@ -275,7 +270,7 @@ fn get_const_cols_ref_fields( f: &syn::Field, generic_type: &syn::TypeParam, const_generics: &[&syn::Ident], -) -> Result { +) -> FieldInfo { let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); @@ -313,7 +308,7 @@ fn get_const_cols_ref_fields( <#elem_type>::width() #(* #dim_exprs)* }; - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { #ndarray_type }, @@ -326,14 +321,14 @@ fn get_const_cols_ref_fields( initializer: quote! { #slice_var }, - }) + } } else if is_columns_struct(&elem_type) { panic!("Arrays of columns structs are currently not supported"); } else if is_generic_type(&elem_type, generic_type) { let length_expr = quote! { 1 #(* #dim_exprs)* }; - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { #ndarray_type }, @@ -345,14 +340,14 @@ fn get_const_cols_ref_fields( initializer: quote! { #slice_var }, - }) + } } else { panic!("Unsupported field type: {:?}", f.ty); } } else if derives_aligned_borrow { // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) let f_ty = &f.ty; - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { &'a #f_ty }, @@ -369,10 +364,10 @@ fn get_const_cols_ref_fields( #slice_var.borrow() } }, - }) + } } else if is_columns_struct(&f.ty) { let const_cols_ref_type = get_const_cols_ref_type(&f.ty, generic_type, parse_quote! { 'a }); - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { #const_cols_ref_type }, @@ -387,9 +382,9 @@ fn get_const_cols_ref_fields( initializer: quote! { #slice_var }, - }) + } } else if is_generic_type(&f.ty, generic_type) { - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { &'a #generic_type }, @@ -403,7 +398,7 @@ fn get_const_cols_ref_fields( initializer: quote! { &#slice_var[0] }, - }) + } } else { panic!("Unsupported field type: {:?}", f.ty); } @@ -414,7 +409,7 @@ fn get_mut_cols_ref_fields( f: &syn::Field, generic_type: &syn::TypeParam, const_generics: &[&syn::Ident], -) -> Result { +) -> FieldInfo { let length_var = format_ident!("{}_length", f.ident.clone().unwrap()); let slice_var = format_ident!("{}_slice", f.ident.clone().unwrap()); @@ -452,7 +447,7 @@ fn get_mut_cols_ref_fields( <#elem_type>::width() #(* #dim_exprs)* }; - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { #ndarray_type }, @@ -465,14 +460,14 @@ fn get_mut_cols_ref_fields( initializer: quote! { #slice_var }, - }) + } } else if is_columns_struct(&elem_type) { panic!("Arrays of columns structs are currently not supported"); } else if is_generic_type(&elem_type, generic_type) { let length_expr = quote! { 1 #(* #dim_exprs)* }; - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { #ndarray_type }, @@ -484,14 +479,14 @@ fn get_mut_cols_ref_fields( initializer: quote! { #slice_var }, - }) + } } else { panic!("Unsupported field type: {:?}", f.ty); } } else if derives_aligned_borrow { // treat the field as a struct that derives AlignedBorrow (and doesn't depend on the config) let f_ty = &f.ty; - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { &'a mut #f_ty }, @@ -508,10 +503,10 @@ fn get_mut_cols_ref_fields( #slice_var.borrow_mut() } }, - }) + } } else if is_columns_struct(&f.ty) { let mut_cols_ref_type = get_mut_cols_ref_type(&f.ty, generic_type); - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { #mut_cols_ref_type }, @@ -526,9 +521,9 @@ fn get_mut_cols_ref_fields( initializer: quote! { #slice_var }, - }) + } } else if is_generic_type(&f.ty, generic_type) { - Ok(FieldInfo { + FieldInfo { ty: parse_quote! { &'a mut #generic_type }, @@ -542,7 +537,7 @@ fn get_mut_cols_ref_fields( initializer: quote! { &mut #slice_var[0] }, - }) + } } else { panic!("Unsupported field type: {:?}", f.ty); } diff --git a/crates/circuits/primitives/derive/src/lib.rs b/crates/circuits/primitives/derive/src/lib.rs index c82545a67a..41b9a1a3bb 100644 --- a/crates/circuits/primitives/derive/src/lib.rs +++ b/crates/circuits/primitives/derive/src/lib.rs @@ -420,14 +420,6 @@ pub fn cols_ref_derive(input: TokenStream) -> TokenStream { .parse_args() .expect("Failed to parse config"); - let span = derive_input.ident.span(); let res = cols_ref_impl(derive_input, config); - res.map_or_else( - |err| { - syn::Error::new(span, err.to_string()) - .to_compile_error() - .into() - }, - |ok| ok.into(), - ) + res.into() } From 2df8c2adb964340f4744cda621dfd77a88de287d Mon Sep 17 00:00:00 2001 From: Avaneesh Kulkarni Date: Mon, 7 Apr 2025 18:06:57 -0400 Subject: [PATCH 27/27] Minor wording changes --- extensions/sha2/circuit/README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/extensions/sha2/circuit/README.md b/extensions/sha2/circuit/README.md index 317c913fe5..de2100b261 100644 --- a/extensions/sha2/circuit/README.md +++ b/extensions/sha2/circuit/README.md @@ -14,18 +14,17 @@ In short the SHA-256 algorithm works as follows. 1. Pad the message to 512 bits and split it into 512-bit 'blocks'. 2. Initialize a hash state consisting of eight 32-bit words to a specific constant value. 3. For each block, - 1. split the message into 16 32-bit words and produce 48 more words based on them. The 16 message word together with the 48 additional words are called the 'message schedule'. + 1. split the message into 16 32-bit words and produce 48 more words based on them. The 16 message words together with the 48 additional words are called the 'message schedule'. 2. apply a scrambling function 64 times to the hash state to update it based on the message schedule. We call each update a 'round'. - 3. add the previous block's final hash state to the current hash state (modulo `2^32`). + 3. add the previous block's final hash state to the current hash state (modulo $2^{32}$). 4. The output is the final hash state The differences with the SHA-512 algorithm are that: -- it uses 64-bit words, 1024-bit blocks, performs 80 rounds, and produces a 512-bit output. -- all the arithmetic is done modulo `2^64`. +- SHA-512 uses 64-bit words, 1024-bit blocks, performs 80 rounds, and produces a 512-bit output. +- all the arithmetic is done modulo $2^{64}$. - the initial hash state is different. -The SHA-384 algorithm is almost exactly a truncation of the SHA-512 output to 384 bits. -The only difference is that the initial hash state is different. +The SHA-384 algorithm is a truncation of the SHA-512 output to 384 bits, and the only difference is that the initial hash state is different. ## Design Overview @@ -38,7 +37,7 @@ The first $R$ rows of each block are called 'round rows', and each of them const Each row constrains updates to the working variables on each round, and also constrains the message schedule words based on previous rounds. The final row of each block is called a 'digest row' and it produces a final hash for the block, computed as the sum of the working variables and the previous block's final hash. -Note that this chip only supports messages of length less than `2^29` bytes. +Note that this chip only supports messages of length less than $2^{29}$ bytes. ### Storing working variables @@ -98,7 +97,7 @@ The `local_block_idx` is used to calculate the length of the message processed s The SHA-2 VM extension chip uses the `Sha2Air` SubAir to help constrain the appropriate SHA-2 hash algorithm. The SubAir is also parameterized by the specific SHA-2 variant's constants. The VM extension AIR constrains the correctness of the message padding, while the SubAir adds all other constraints related to the hash algorithm. -The VM extension air also constrains memory reads and writes. +The VM extension AIR also constrains memory reads and writes. ### A gotcha about padding rows