use std::cell::RefCell;
use arbitrary::Arbitrary;
pub const ENV_VAR_LDE_CACHE: &str = "TVM_LDE_TRACE";
pub const ENV_VAR_LDE_CACHE_WITH_CACHE: &str = "cache";
pub const ENV_VAR_LDE_CACHE_NO_CACHE: &str = "no_cache";
thread_local! {
pub(crate) static CONFIG: RefCell<Config> = RefCell::new(Config::default());
}
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Arbitrary)]
pub enum CacheDecision {
#[default]
Cache,
NoCache,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Arbitrary)]
struct Config {
pub cache_lde_trace_overwrite: Option<CacheDecision>,
}
impl Config {
pub fn new() -> Self {
let maybe_overwrite = std::env::var(ENV_VAR_LDE_CACHE).map(|s| s.to_ascii_lowercase());
let cache_lde_trace_overwrite = match maybe_overwrite {
Ok(t) if t == ENV_VAR_LDE_CACHE_WITH_CACHE => Some(CacheDecision::Cache),
Ok(f) if f == ENV_VAR_LDE_CACHE_NO_CACHE => Some(CacheDecision::NoCache),
_ => None,
};
Self {
cache_lde_trace_overwrite,
}
}
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
pub fn overwrite_lde_trace_caching_to(decision: CacheDecision) {
CONFIG.with_borrow_mut(|config| config.cache_lde_trace_overwrite = Some(decision));
}
pub(crate) fn cache_lde_trace() -> Option<CacheDecision> {
CONFIG.with_borrow(|config| config.cache_lde_trace_overwrite)
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use crate::example_programs::FIBONACCI_SEQUENCE;
use crate::prelude::*;
use crate::shared_tests::TestableProgram;
use super::*;
#[test]
fn triton_vm_can_generate_valid_proof_with_just_in_time_lde() {
overwrite_lde_trace_caching_to(CacheDecision::NoCache);
prove_and_verify_a_triton_vm_program();
}
#[test]
fn triton_vm_can_generate_valid_proof_with_cached_lde_trace() {
overwrite_lde_trace_caching_to(CacheDecision::Cache);
prove_and_verify_a_triton_vm_program();
}
fn prove_and_verify_a_triton_vm_program() {
TestableProgram::new(FIBONACCI_SEQUENCE.clone())
.with_input(PublicInput::from(bfe_array![100]))
.prove_and_verify();
}
}