Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13,842 changes: 7,112 additions & 6,730 deletions circuit_defs/bigint_with_control/generated/quotient.rs

Large diffs are not rendered by default.

13,842 changes: 7,112 additions & 6,730 deletions circuit_defs/bigint_with_control/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

26,061 changes: 14,867 additions & 11,194 deletions circuit_defs/blake2_with_compression/generated/quotient.rs

Large diffs are not rendered by default.

26,061 changes: 14,867 additions & 11,194 deletions circuit_defs/blake2_with_compression/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

3,900 changes: 1,970 additions & 1,930 deletions circuit_defs/final_reduced_risc_v_machine/generated/quotient.rs

Large diffs are not rendered by default.

3,900 changes: 1,970 additions & 1,930 deletions circuit_defs/final_reduced_risc_v_machine/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

4,898 changes: 2,469 additions & 2,429 deletions circuit_defs/machine_without_signed_mul_div/generated/quotient.rs

Large diffs are not rendered by default.

4,898 changes: 2,469 additions & 2,429 deletions circuit_defs/machine_without_signed_mul_div/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

3,900 changes: 1,970 additions & 1,930 deletions circuit_defs/reduced_risc_v_log_23_machine/generated/quotient.rs

Large diffs are not rendered by default.

3,900 changes: 1,970 additions & 1,930 deletions circuit_defs/reduced_risc_v_log_23_machine/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

3,924 changes: 1,982 additions & 1,942 deletions circuit_defs/reduced_risc_v_machine/generated/quotient.rs

Large diffs are not rendered by default.

3,924 changes: 1,982 additions & 1,942 deletions circuit_defs/reduced_risc_v_machine/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

5,363 changes: 2,706 additions & 2,657 deletions circuit_defs/risc_v_cycles/generated/quotient.rs

Large diffs are not rendered by default.

5,363 changes: 2,706 additions & 2,657 deletions circuit_defs/risc_v_cycles/verifier/src/generated/quotient.rs

Large diffs are not rendered by default.

Binary file modified tools/verifier/base_layer_with_output.bin
Binary file not shown.
Binary file modified tools/verifier/final_recursion_layer_with_output.bin
Binary file not shown.
Binary file modified tools/verifier/recursion_layer_no_delegation_with_output.bin
Binary file not shown.
Binary file modified tools/verifier/recursion_layer_with_output.bin
Binary file not shown.
Binary file modified tools/verifier/recursion_log_23_layer_with_output.bin
Binary file not shown.
Binary file modified tools/verifier/universal.bin
Binary file not shown.
20 changes: 10 additions & 10 deletions tools/verifier/universal.reduced.vk.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"machine_type": "Reduced",
"bytecode_hash_hex": "e35b3a128022a048e891ef5d2a373ed8ad128a587d019000f8ebb44e2fa63e43",
"bytecode_hash_hex": "9e628f26b6e5fc422ac999a3cddda7b12c1ffeca98db918df3db48412a8e03d1",
"params": [
860058423,
3640415478,
2384303882,
1724860185,
4002833746,
400750227,
1814308475,
3620614667
1834943447,
3437434522,
2531669520,
372435254,
1699984500,
2703074746,
2308512171,
629659177
],
"params_hex": "33437337d8fc54f68e1d970a66cf4719ee96655217e2f6936c24267bd7ce320b"
"params_hex": "6d5f03d7cce3169a96e636101632e9366553b474a11da5ba899919ab2587d629"
}
20 changes: 10 additions & 10 deletions tools/verifier/universal.reduced_log23.vk.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"machine_type": "ReducedLog23",
"bytecode_hash_hex": "e35b3a128022a048e891ef5d2a373ed8ad128a587d019000f8ebb44e2fa63e43",
"bytecode_hash_hex": "9e628f26b6e5fc422ac999a3cddda7b12c1ffeca98db918df3db48412a8e03d1",
"params": [
1769135556,
2750069066,
261141979,
1444565367,
2056362079,
3466625596,
3123703739,
836672824
2516507352,
3030059435,
3850063554,
802327088,
1929587345,
3560376621,
3929673216,
3717490096
],
"params_hex": "6972ddc4a3eab94a0f90b5db561a51777a91985fcea0823cba2fefbb31de9d38"
"params_hex": "95fedad8b49b09abe57b4ec22fd28a3073032a91d437092dea3a0e00dd9465b0"
}
Binary file modified tools/verifier/universal_no_delegation.bin
Binary file not shown.
20 changes: 10 additions & 10 deletions tools/verifier/universal_no_delegation.final.vk.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"machine_type": "ReducedFinal",
"bytecode_hash_hex": "9247f4c84d6a5b4472f374e87688910f14fad55ed7a9587c67f8295512c55389",
"bytecode_hash_hex": "6274591dce6e1c8202ccbb99f2510179d226877cc4875d50e34c175a1a451de2",
"params": [
2224705490,
2565817870,
3003796587,
14309538,
4275886385,
534049063,
1788641825,
4135795200
736415485,
2857284559,
1798178369,
888098281,
127866363,
1930712508,
3224487278,
2151144270
],
"params_hex": "849a4fd298ef460eb30a4c6b00da58a2fedcd9311fd4f1276a9c8221f6833a00"
"params_hex": "2be4cefdaa4eb3cf6b2e064134ef4de9079f15fb731455bcc031c56e8037db4e"
}
61 changes: 61 additions & 0 deletions verifier_common/src/inline_ops.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use field::{Field, FieldExtension};

// RISC-V verifier builds benefit from preserving direct inlined arithmetic,
// so generated quotient code can use this module as the fast-path backend.

#[inline(always)]
pub fn add_assign<'a, T: Field>(lhs: &'a mut T, rhs: &T) -> &'a mut T {
lhs.add_assign(rhs)
}

#[inline(always)]
pub fn sub_assign<'a, T: Field>(lhs: &'a mut T, rhs: &T) -> &'a mut T {
lhs.sub_assign(rhs)
}

#[inline(always)]
pub fn mul_assign<'a, T: Field>(lhs: &'a mut T, rhs: &T) -> &'a mut T {
lhs.mul_assign(rhs)
}

#[inline(always)]
pub fn negate<T: Field>(lhs: &mut T) -> &mut T {
lhs.negate()
}

#[inline(always)]
pub fn square<T: Field>(lhs: &mut T) -> &mut T {
lhs.square()
}

#[inline(always)]
pub fn double<T: Field>(lhs: &mut T) -> &mut T {
lhs.double()
}

#[inline(always)]
pub fn add_assign_base<'a, T, Base>(lhs: &'a mut T, rhs: &Base) -> &'a mut T
where
Base: Field,
T: FieldExtension<Base>,
{
lhs.add_assign_base(rhs)
}

#[inline(always)]
pub fn sub_assign_base<'a, T, Base>(lhs: &'a mut T, rhs: &Base) -> &'a mut T
where
Base: Field,
T: FieldExtension<Base>,
{
lhs.sub_assign_base(rhs)
}

#[inline(always)]
pub fn mul_assign_by_base<'a, T, Base>(lhs: &'a mut T, rhs: &Base) -> &'a mut T
where
Base: Field,
T: FieldExtension<Base>,
{
lhs.mul_assign_by_base(rhs)
}
15 changes: 15 additions & 0 deletions verifier_common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ pub mod fri_folding;
#[cfg(any(test, feature = "proof_utils"))]
pub mod proof_flattener;

pub mod inline_ops;
pub mod no_inline_ops;

/// Wrappers for common field operations used by the verifier.
/// We use inline operations when compiling to RISC-V to maximize performance,
/// but using inline operations on x86_64 causes compile time to explode.
/// On host platforms we disable inlining to keep compile times sane.
pub mod field_ops {
#[cfg(target_arch = "riscv32")]
pub use crate::inline_ops::*;

#[cfg(not(target_arch = "riscv32"))]
pub use crate::no_inline_ops::*;
}

pub mod structs;

#[cfg(not(target_arch = "riscv32"))]
Expand Down
62 changes: 62 additions & 0 deletions verifier_common/src/no_inline_ops.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use field::{Field, FieldExtension};

// Verifier quotient code can be very large once inlined constraints are expanded.
// These wrappers keep hot arithmetic calls out-of-line to reduce compile-time blowup
// in verifier-only crates, while prover code keeps using direct field methods.

#[inline(never)]
pub fn add_assign<'a, T: Field>(lhs: &'a mut T, rhs: &T) -> &'a mut T {
lhs.add_assign(rhs)
}

#[inline(never)]
pub fn sub_assign<'a, T: Field>(lhs: &'a mut T, rhs: &T) -> &'a mut T {
lhs.sub_assign(rhs)
}

#[inline(never)]
pub fn mul_assign<'a, T: Field>(lhs: &'a mut T, rhs: &T) -> &'a mut T {
lhs.mul_assign(rhs)
}

#[inline(never)]
pub fn negate<T: Field>(lhs: &mut T) -> &mut T {
lhs.negate()
}

#[inline(never)]
pub fn square<T: Field>(lhs: &mut T) -> &mut T {
lhs.square()
}

#[inline(never)]
pub fn double<T: Field>(lhs: &mut T) -> &mut T {
lhs.double()
}

#[inline(never)]
pub fn add_assign_base<'a, T, Base>(lhs: &'a mut T, rhs: &Base) -> &'a mut T
where
Base: Field,
T: FieldExtension<Base>,
{
lhs.add_assign_base(rhs)
}

#[inline(never)]
pub fn sub_assign_base<'a, T, Base>(lhs: &'a mut T, rhs: &Base) -> &'a mut T
where
Base: Field,
T: FieldExtension<Base>,
{
lhs.sub_assign_base(rhs)
}

#[inline(never)]
pub fn mul_assign_by_base<'a, T, Base>(lhs: &'a mut T, rhs: &Base) -> &'a mut T
where
Base: Field,
T: FieldExtension<Base>,
{
lhs.mul_assign_by_base(rhs)
}
2 changes: 1 addition & 1 deletion verifier_generator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories.workspace = true
[dependencies]
prover = { workspace = true, features = ["prover"] }
serde.workspace = true
syn = { version = "2", features = ["extra-traits", "printing", "full"]}
syn = { version = "2", features = ["extra-traits", "printing", "full", "visit-mut"]}
quote = { version = "1" }
proc-macro2 = "1"
proc-macro-error2 = "2.0"
Expand Down
96 changes: 93 additions & 3 deletions verifier_generator/src/inlining_generator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::*;

use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::Ident;
use quote::{quote, ToTokens};
use syn::{visit_mut::VisitMut, Expr, File, Ident, Item};

mod everywhere_except_last;
mod memory_accumulators;
Expand Down Expand Up @@ -563,7 +563,7 @@ pub fn generate_inlined(compiled_circuit: CompiledCircuitArtifact<Mersenne31Fiel

let num_different_divisors = NUM_DIFFERENT_DIVISORS;

quote! {
rewrite_field_ops_calls(quote! {

#[allow(unused_braces, unused_mut, unused_variables)]
unsafe fn evaluate_every_row_except_last(
Expand Down Expand Up @@ -843,5 +843,95 @@ pub fn generate_inlined(compiled_circuit: CompiledCircuitArtifact<Mersenne31Fiel

quotient
}
})
}

// The inlining generator still builds expressions using field trait methods.
// For verifier code, we rewrite those method calls into `verifier_common::field_ops`
// wrappers so host builds can switch to `#[inline(never)]` implementations.
fn rewrite_field_ops_calls(tokens: TokenStream) -> TokenStream {
let mut file: File = syn::parse2(tokens).expect("generated verifier code must parse");
let mut rewriter = FieldOpsCallRewriter::default();
rewriter.visit_file_mut(&mut file);

if rewriter.rewrite_happened {
let has_field_ops_import = file.items.iter().any(|item| {
if let Item::Use(item_use) = item {
item_use
.to_token_stream()
.to_string()
.contains("verifier_common :: field_ops")
} else {
false
}
});

if !has_field_ops_import {
file.items
.insert(0, syn::parse_quote! { use ::verifier_common::field_ops; });
}
}

quote! { #file }
}

#[derive(Default)]
struct FieldOpsCallRewriter {
rewrite_happened: bool,
}

impl VisitMut for FieldOpsCallRewriter {
fn visit_expr_mut(&mut self, expr: &mut Expr) {
syn::visit_mut::visit_expr_mut(self, expr);

let Expr::MethodCall(method_call) = expr else {
return;
};

let method_name = method_call.method.to_string();
let receiver = (*method_call.receiver).clone();
let args: Vec<Expr> = method_call.args.iter().cloned().collect();

let replacement = match method_name.as_str() {
"add_assign" if args.len() == 1 => {
let arg = args[0].clone();
Some(syn::parse_quote! { field_ops::add_assign(&mut #receiver, #arg) })
}
"sub_assign" if args.len() == 1 => {
let arg = args[0].clone();
Some(syn::parse_quote! { field_ops::sub_assign(&mut #receiver, #arg) })
}
"mul_assign" if args.len() == 1 => {
let arg = args[0].clone();
Some(syn::parse_quote! { field_ops::mul_assign(&mut #receiver, #arg) })
}
"add_assign_base" if args.len() == 1 => {
let arg = args[0].clone();
Some(syn::parse_quote! { field_ops::add_assign_base(&mut #receiver, #arg) })
}
"sub_assign_base" if args.len() == 1 => {
let arg = args[0].clone();
Some(syn::parse_quote! { field_ops::sub_assign_base(&mut #receiver, #arg) })
}
"mul_assign_by_base" if args.len() == 1 => {
let arg = args[0].clone();
Some(syn::parse_quote! { field_ops::mul_assign_by_base(&mut #receiver, #arg) })
}
"negate" if args.is_empty() => {
Some(syn::parse_quote! { field_ops::negate(&mut #receiver) })
}
"square" if args.is_empty() => {
Some(syn::parse_quote! { field_ops::square(&mut #receiver) })
}
"double" if args.is_empty() => {
Some(syn::parse_quote! { field_ops::double(&mut #receiver) })
}
_ => None,
};

if let Some(replacement) = replacement {
self.rewrite_happened = true;
*expr = replacement;
}
}
}
Loading