Skip to content

Commit

Permalink
Add execution options for processor and prover (#991)
Browse files Browse the repository at this point in the history
* feat: implement ExecutionOptions for the processor and prover

* refactor: move to another file, add validation

* refactor: improve comments, names and format
  • Loading branch information
Fumuran authored Jul 18, 2023
1 parent 602d185 commit f2d9e8f
Show file tree
Hide file tree
Showing 17 changed files with 318 additions and 153 deletions.
27 changes: 27 additions & 0 deletions air/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use super::String;
use core::fmt::{Display, Formatter};

// EXECUTION ERROR
// ================================================================================================

#[derive(Debug)]
pub enum ExecutionOptionsError {
ExpectedCyclesTooBig(u32, u32),
OtherErrors(String),
}

impl Display for ExecutionOptionsError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
use ExecutionOptionsError::*;

match self {
ExpectedCyclesTooBig(max, expected) => {
write!(f, "The expected number of cycles must be smaller than the maximum number of cycles: maximum is {max}, but expectd is {expected}")
}
OtherErrors(error) => write!(f, "{error}"),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for ExecutionOptionsError {}
8 changes: 6 additions & 2 deletions air/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
extern crate alloc;

use vm_core::{
utils::{collections::Vec, ByteWriter, Serializable},
utils::{collections::Vec, string::String, ByteWriter, Serializable},
ExtensionOf, ProgramInfo, StackInputs, StackOutputs, ONE, ZERO,
};
use winter_air::{
Expand All @@ -20,6 +20,8 @@ use constraints::{chiplets, range};
pub mod trace;
use trace::*;

mod errors;
mod options;
mod proof;

mod utils;
Expand All @@ -28,7 +30,9 @@ use utils::TransitionConstraintRange;
// EXPORTS
// ================================================================================================

pub use proof::{ExecutionProof, HashFunction, ProofOptions};
pub use errors::ExecutionOptionsError;
pub use options::{ExecutionOptions, ProvingOptions};
pub use proof::{ExecutionProof, HashFunction};
pub use vm_core::{
utils::{DeserializationError, ToElements},
Felt, FieldElement, StarkField,
Expand Down
169 changes: 169 additions & 0 deletions air/src/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
use super::{ExecutionOptionsError, HashFunction};
use winter_air::{FieldExtension, ProofOptions as WinterProofOptions};

// PROVING OPTIONS
// ================================================================================================

/// A set of parameters specifying how Miden VM execution proofs are to be generated.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ProvingOptions {
pub exec_options: ExecutionOptions,
pub proof_options: WinterProofOptions,
pub hash_fn: HashFunction,
}

impl ProvingOptions {
// CONSTRUCTOR
// --------------------------------------------------------------------------------------------

/// Creates a new instance of [ProvingOptions] from the specified parameters.
pub fn new(
num_queries: usize,
blowup_factor: usize,
grinding_factor: u32,
field_extension: FieldExtension,
fri_folding_factor: usize,
fri_remainder_max_degree: usize,
hash_fn: HashFunction,
) -> Self {
let proof_options = WinterProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor,
fri_remainder_max_degree,
);
let exec_options = ExecutionOptions::default();
Self {
exec_options,
proof_options,
hash_fn,
}
}

/// Creates a new preset instance of [ProvingOptions] targeting 96-bit security level.
///
/// If `recursive` flag is set to true, proofs will be generated using an arithmetization-
/// friendly hash function (RPO). Such proofs are well-suited for recursive proof verification,
/// but may take significantly longer to generate.
pub fn with_96_bit_security(recursive: bool) -> Self {
if recursive {
let proof_options = WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 4, 7);
Self {
exec_options: ExecutionOptions::default(),
proof_options,
hash_fn: HashFunction::Rpo256,
}
} else {
let proof_options =
WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 8, 255);
Self {
exec_options: ExecutionOptions::default(),
proof_options,
hash_fn: HashFunction::Blake3_192,
}
}
}

/// Creates a new preset instance of [ProvingOptions] targeting 128-bit security level.
///
/// If `recursive` flag is set to true, proofs will be generated using an arithmetization-
/// friendly hash function (RPO). Such proofs are well-suited for recursive proof verification,
/// but may take significantly longer to generate.
pub fn with_128_bit_security(recursive: bool) -> Self {
if recursive {
let proof_options = WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 4, 7);
Self {
exec_options: ExecutionOptions::default(),
proof_options,
hash_fn: HashFunction::Rpo256,
}
} else {
let proof_options = WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 8, 255);
Self {
exec_options: ExecutionOptions::default(),
proof_options,
hash_fn: HashFunction::Blake3_256,
}
}
}

/// Sets [ExecutionOptions] for this [ProvingOptions].
///
/// This sets the maximum number of cycles a program is allowed to execute as well as
/// the number of cycles the program is expected to execute.
pub fn with_execution_options(mut self, exec_options: ExecutionOptions) -> Self {
self.exec_options = exec_options;
self
}

// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------

/// Returns the hash function to be used in STARK proof generation.
pub const fn hash_fn(&self) -> HashFunction {
self.hash_fn
}

/// Returns the execution options specified for this [ProvingOptions]
pub const fn execution_options(&self) -> &ExecutionOptions {
&self.exec_options
}
}

impl Default for ProvingOptions {
fn default() -> Self {
Self::with_96_bit_security(false)
}
}

impl From<ProvingOptions> for WinterProofOptions {
fn from(options: ProvingOptions) -> Self {
options.proof_options
}
}

// EXECUTION OPTIONS
// ================================================================================================

/// A set of parameters specifying execution parameters of the VM.
///
/// - `max_cycles` specifies the maximum number of cycles a program is allowed to execute.
/// - `expected_cycles` specifies the number of cycles a program is expected to execute.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExecutionOptions {
max_cycles: Option<u32>,
expected_cycles: u32,
}

impl Default for ExecutionOptions {
fn default() -> Self {
ExecutionOptions {
max_cycles: None,
expected_cycles: 64,
}
}
}

impl ExecutionOptions {
// CONSTRUCTOR
// --------------------------------------------------------------------------------------------

/// Creates a new instance of [ExecutionOptions] from the specified parameters.
pub fn new(
max_cycles: Option<u32>,
expected_cycles: u32,
) -> Result<Self, ExecutionOptionsError> {
if max_cycles.is_some_and(|max_cycles| max_cycles < expected_cycles) {
return Err(ExecutionOptionsError::ExpectedCyclesTooBig(
max_cycles.unwrap(),
expected_cycles,
));
}
Ok(ExecutionOptions {
max_cycles,
expected_cycles,
})
}
}
100 changes: 1 addition & 99 deletions air/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use vm_core::{
crypto::hash::{Blake3_192, Blake3_256, Hasher, Rpo256},
utils::collections::Vec,
};
use winter_air::{proof::StarkProof, FieldExtension, ProofOptions as WinterProofOptions};
use winter_air::proof::StarkProof;

// EXECUTION PROOF
// ================================================================================================
Expand Down Expand Up @@ -81,104 +81,6 @@ impl ExecutionProof {
}
}

// PROOF OPTIONS
// ================================================================================================

/// A set of parameters specifying how Miden VM execution proofs are to be generated.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ProofOptions {
pub options: WinterProofOptions,
pub hash_fn: HashFunction,
}

impl ProofOptions {
// CONSTRUCTOR
// --------------------------------------------------------------------------------------------

/// Creates a new instance of [ProofOptions] from the specified parameters.
pub fn new(
num_queries: usize,
blowup_factor: usize,
grinding_factor: u32,
field_extension: FieldExtension,
fri_folding_factor: usize,
fri_max_remainder_size: usize,
hash_fn: HashFunction,
) -> Self {
let options = WinterProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor,
fri_max_remainder_size,
);
Self { options, hash_fn }
}

/// Creates a new preset instance of [ProofOptions] targeting 96-bit security level.
///
/// If `recursive` flag is set to true, proofs will be generated using an arithmetization-
/// friendly hash function (RPO). Such proofs are well-suited for recursive proof verification,
/// but may take significantly longer to generate.
pub fn with_96_bit_security(recursive: bool) -> Self {
if recursive {
let options = WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 4, 7);
Self {
hash_fn: HashFunction::Rpo256,
options,
}
} else {
let options = WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 8, 255);
Self {
hash_fn: HashFunction::Blake3_192,
options,
}
}
}

/// Creates a new preset instance of [ProofOptions] targeting 128-bit security level.
///
/// If `recursive` flag is set to true, proofs will be generated using an arithmetization-
/// friendly hash function (RPO). Such proofs are well-suited for recursive proof verification,
/// but may take significantly longer to generate.
pub fn with_128_bit_security(recursive: bool) -> Self {
if recursive {
let options = WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 4, 7);
Self {
hash_fn: HashFunction::Rpo256,
options,
}
} else {
let options = WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 8, 255);
Self {
hash_fn: HashFunction::Blake3_256,
options,
}
}
}

// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------

/// Returns the hash function to be used in STARK proof generation.
pub const fn hash_fn(&self) -> HashFunction {
self.hash_fn
}
}

impl Default for ProofOptions {
fn default() -> Self {
Self::with_96_bit_security(false)
}
}

impl From<ProofOptions> for WinterProofOptions {
fn from(options: ProofOptions) -> Self {
options.options
}
}

// HASH FUNCTION
// ================================================================================================

Expand Down
Loading

0 comments on commit f2d9e8f

Please sign in to comment.