tasm_lib/verifier/challenges/
new_generic_dyn_claim.rsuse num::One;
use triton_vm::air::challenge_id::ChallengeId;
use triton_vm::air::cross_table_argument::CrossTableArg;
use triton_vm::air::cross_table_argument::EvalArg;
use triton_vm::challenges::Challenges;
use triton_vm::prelude::*;
use triton_vm::twenty_first::math::x_field_element::EXTENSION_DEGREE;
use crate::data_type::DataType;
use crate::hashing::algebraic_hasher::sample_scalars_static_length_static_pointer::SampleScalarsStaticLengthStaticPointer;
use crate::library::Library;
use crate::tip5::Digest;
use crate::traits::basic_snippet::BasicSnippet;
use crate::verifier::challenges::shared::challenges_data_type;
use crate::verifier::claim::shared::claim_type;
use crate::verifier::eval_arg::compute_terminal_const_sized_static_symbols::ComputeTerminalConstSizedStaticSymbols;
use crate::verifier::eval_arg::compute_terminal_dyn_sized_dynamic_symbols::ComputeTerminalDynSizedDynamicSymbols;
use crate::verifier::eval_arg::compute_terminal_from_digest::ComputeTerminalFromDigestInitialIsOne;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct NewGenericDynClaim {
num_of_fiat_shamir_challenges: usize,
num_of_claim_derived_challenges: usize,
pub challenges_pointer: BFieldElement,
}
impl NewGenericDynClaim {
pub fn tvm_challenges(challenges_pointer: BFieldElement) -> Self {
Self {
num_of_fiat_shamir_challenges: Challenges::SAMPLE_COUNT,
num_of_claim_derived_challenges: ChallengeId::NUM_DERIVED_CHALLENGES,
challenges_pointer,
}
}
pub fn new(
num_challenges_to_sample: usize,
num_challenges_to_compute: usize,
challenges_pointer: BFieldElement,
) -> Self {
Self {
num_of_fiat_shamir_challenges: num_challenges_to_sample,
num_of_claim_derived_challenges: num_challenges_to_compute,
challenges_pointer,
}
}
fn total_number_of_challenges_returned(&self) -> usize {
self.num_of_fiat_shamir_challenges + self.num_of_claim_derived_challenges
}
fn sample_scalars_snippet(&self) -> SampleScalarsStaticLengthStaticPointer {
SampleScalarsStaticLengthStaticPointer {
num_elements_to_sample: self.num_of_fiat_shamir_challenges,
extra_capacity: self.num_of_claim_derived_challenges,
scalars_pointer: self.challenges_pointer,
}
}
}
impl BasicSnippet for NewGenericDynClaim {
fn inputs(&self) -> Vec<(DataType, String)> {
vec![(DataType::StructRef(claim_type()), "*claim".to_owned())]
}
fn outputs(&self) -> Vec<(DataType, String)> {
vec![(
challenges_data_type(self.total_number_of_challenges_returned()),
"challenges".to_owned(),
)]
}
fn entrypoint(&self) -> String {
format!(
"tasmlib_verifier_challenges_new_generic_dyn_claim_{}_{}",
self.num_of_fiat_shamir_challenges, self.num_of_claim_derived_challenges,
)
}
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
let entrypoint = self.entrypoint();
let sample_scalars_snippet = self.sample_scalars_snippet();
let sample_scalars = library.import(Box::new(sample_scalars_snippet));
let compute_compressed_digest =
library.import(Box::new(ComputeTerminalFromDigestInitialIsOne));
let calculate_lookup_terminal =
library.import(Box::new(ComputeTerminalConstSizedStaticSymbols {
symbols: tip5::LOOKUP_TABLE.map(|i| BFieldElement::new(i as u64)),
initial: XFieldElement::one(),
}));
let calculate_io_terminal = library.import(Box::new(ComputeTerminalDynSizedDynamicSymbols));
let scalars_pointer = self.challenges_pointer;
let scalar_write_index = |i: ChallengeId| {
scalars_pointer.value() + u64::try_from(i.index() * EXTENSION_DEGREE).unwrap()
};
let scalar_read_index =
|i: ChallengeId| scalar_write_index(i) + u64::try_from(EXTENSION_DEGREE - 1).unwrap();
let default_initial = EvalArg::default_initial();
triton_asm!(
{entrypoint}:
call {sample_scalars}
push {scalar_read_index(ChallengeId::StandardOutputIndeterminate)}
read_mem {EXTENSION_DEGREE}
pop 1
push {default_initial.coefficients[2]}
push {default_initial.coefficients[1]}
push {default_initial.coefficients[0]}
dup 6
push 1
add
call {calculate_io_terminal}
push {scalar_write_index(ChallengeId::StandardOutputTerminal)}
write_mem {EXTENSION_DEGREE}
pop 1
push {scalar_read_index(ChallengeId::StandardInputIndeterminate)}
read_mem {EXTENSION_DEGREE}
pop 1
push {default_initial.coefficients[2]}
push {default_initial.coefficients[1]}
push {default_initial.coefficients[0]}
dup 6
read_mem 1
push 3
add
add
dup 0
swap 8
pop 1
call {calculate_io_terminal}
push {scalar_write_index(ChallengeId::StandardInputTerminal)}
write_mem {EXTENSION_DEGREE}
pop 1
read_mem 1
addi {1 + 1 + Digest::LEN} add
push {scalar_read_index(ChallengeId::CompressProgramDigestIndeterminate)}
read_mem {EXTENSION_DEGREE}
pop 1
dup 3
read_mem {Digest::LEN}
pop 1
call {compute_compressed_digest}
push {scalar_write_index(ChallengeId::CompressedProgramDigest)}
write_mem {EXTENSION_DEGREE}
pop 2
push {scalar_read_index(ChallengeId::LookupTablePublicIndeterminate)}
read_mem {EXTENSION_DEGREE}
pop 1
call {calculate_lookup_terminal}
push {scalar_write_index(ChallengeId::LookupTablePublicTerminal)}
write_mem {EXTENSION_DEGREE}
pop 1
push {scalars_pointer}
return
)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use rand::prelude::*;
use triton_vm::challenges::Challenges;
use triton_vm::twenty_first::math::other::random_elements;
use triton_vm::twenty_first::util_types::algebraic_hasher::AlgebraicHasher;
use super::*;
use crate::memory::encode_to_memory;
use crate::rust_shadowing_helper_functions::array::insert_as_array;
use crate::rust_shadowing_helper_functions::claim::load_claim_from_memory;
use crate::snippet_bencher::BenchmarkCase;
use crate::traits::basic_snippet::BasicSnippet;
use crate::traits::procedure::Procedure;
use crate::traits::procedure::ProcedureInitialState;
use crate::traits::procedure::ShadowedProcedure;
use crate::traits::rust_shadow::RustShadow;
use crate::verifier::challenges::shared::conventional_challenges_pointer;
use crate::VmHasher;
impl Procedure for NewGenericDynClaim {
fn rust_shadow(
&self,
stack: &mut Vec<BFieldElement>,
memory: &mut HashMap<BFieldElement, BFieldElement>,
_nondeterminism: &NonDeterminism,
_public_input: &[BFieldElement],
sponge: &mut Option<VmHasher>,
) -> Vec<BFieldElement> {
let sponge = sponge.as_mut().expect("sponge must be initialized");
let claim_pointer = stack.pop().unwrap();
let claim = load_claim_from_memory(claim_pointer, memory);
let challenges = sponge.sample_scalars(self.num_of_fiat_shamir_challenges);
let challenges = Challenges::new(challenges, &claim);
let challenges_pointer = self.challenges_pointer;
stack.push(challenges_pointer);
insert_as_array(challenges_pointer, memory, challenges.challenges.to_vec());
vec![]
}
fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
bench_case: Option<BenchmarkCase>,
) -> ProcedureInitialState {
let mut rng: StdRng = SeedableRng::from_seed(seed);
let (input_length, output_length) = match bench_case {
Some(BenchmarkCase::CommonCase) => (0, 0),
Some(BenchmarkCase::WorstCase) => (100, 100),
None => (rng.gen_range(0..1000), rng.gen_range(0..1000)),
};
let claim = Claim::new(rng.gen())
.with_input(random_elements(input_length))
.with_output(random_elements(output_length));
let mut memory = HashMap::default();
let claim_pointer = rng.gen();
encode_to_memory(&mut memory, claim_pointer, &claim);
let stack = [self.init_stack_for_isolated_run(), vec![claim_pointer]].concat();
let sponge = Tip5 { state: rng.gen() };
ProcedureInitialState {
stack,
sponge: Some(sponge),
nondeterminism: NonDeterminism::default().with_ram(memory),
public_input: vec![],
}
}
}
#[test]
fn new_challenges_pbt() {
ShadowedProcedure::new(NewGenericDynClaim::tvm_challenges(
conventional_challenges_pointer(),
))
.test();
}
}
#[cfg(test)]
mod benches {
use super::super::shared::conventional_challenges_pointer;
use super::*;
use crate::traits::procedure::ShadowedProcedure;
use crate::traits::rust_shadow::RustShadow;
#[test]
fn bench_for_challenges_calc_for_recufier() {
ShadowedProcedure::new(NewGenericDynClaim::tvm_challenges(
conventional_challenges_pointer(),
))
.bench();
}
}