tasm_lib/verifier/challenges/
new_empty_input_and_output.rs1use num::One;
2use triton_vm::air::challenge_id::ChallengeId;
3use triton_vm::air::cross_table_argument::CrossTableArg;
4use triton_vm::air::cross_table_argument::EvalArg;
5use triton_vm::prelude::*;
6use twenty_first::math::x_field_element::EXTENSION_DEGREE;
7
8use crate::hashing::algebraic_hasher::sample_scalars_static_length_static_pointer::SampleScalarsStaticLengthStaticPointer;
9use crate::prelude::*;
10use crate::verifier::challenges::shared::challenges_data_type;
11use crate::verifier::eval_arg::compute_terminal_const_sized_static_symbols::ComputeTerminalConstSizedStaticSymbols;
12use crate::verifier::eval_arg::compute_terminal_from_digest::ComputeTerminalFromDigestInitialIsOne;
13
14#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
15pub struct NewEmptyInputAndOutput {
16 num_of_fiat_shamir_challenges: usize,
19 num_of_claim_derived_challenges: usize,
20
21 pub challenges_pointer: BFieldElement,
23}
24
25impl NewEmptyInputAndOutput {
26 pub fn new(
27 num_challenges_to_sample: usize,
28 num_challenges_to_compute: usize,
29 challenges_pointer: BFieldElement,
30 ) -> Self {
31 Self {
32 num_of_fiat_shamir_challenges: num_challenges_to_sample,
33 num_of_claim_derived_challenges: num_challenges_to_compute,
34 challenges_pointer,
35 }
36 }
37
38 fn total_number_of_challenges_returned(&self) -> usize {
39 self.num_of_fiat_shamir_challenges + self.num_of_claim_derived_challenges
40 }
41
42 fn sample_scalars_snippet(&self) -> SampleScalarsStaticLengthStaticPointer {
43 SampleScalarsStaticLengthStaticPointer {
44 num_elements_to_sample: self.num_of_fiat_shamir_challenges,
45 extra_capacity: self.num_of_claim_derived_challenges,
46 scalars_pointer: self.challenges_pointer,
47 }
48 }
49}
50
51impl BasicSnippet for NewEmptyInputAndOutput {
52 fn inputs(&self) -> Vec<(DataType, String)> {
53 vec![(DataType::Digest, "program_digest".to_owned())]
54 }
55
56 fn outputs(&self) -> Vec<(DataType, String)> {
57 vec![(
58 challenges_data_type(self.total_number_of_challenges_returned()),
59 "challenges".to_owned(),
60 )]
61 }
62
63 fn entrypoint(&self) -> String {
64 format!(
65 "tasmlib_verifier_challenges_new_empty_input_and_output_{}_{}",
66 self.num_of_fiat_shamir_challenges, self.num_of_claim_derived_challenges,
67 )
68 }
69
70 fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
71 let entrypoint = self.entrypoint();
72 let sample_scalars_snippet = self.sample_scalars_snippet();
73 let sample_scalars = library.import(Box::new(sample_scalars_snippet));
74 let compute_compressed_digest =
75 library.import(Box::new(ComputeTerminalFromDigestInitialIsOne));
76 let calculate_lookup_terminal =
77 library.import(Box::new(ComputeTerminalConstSizedStaticSymbols {
78 symbols: tip5::LOOKUP_TABLE.map(|i| BFieldElement::new(i as u64)),
79 initial: XFieldElement::one(),
80 }));
81
82 let scalars_pointer = self.challenges_pointer;
83 let scalar_write_index = |i: ChallengeId| {
84 scalars_pointer.value() + u64::try_from(i.index() * EXTENSION_DEGREE).unwrap()
85 };
86 let scalar_read_index =
87 |i: ChallengeId| scalar_write_index(i) + u64::try_from(EXTENSION_DEGREE - 1).unwrap();
88
89 triton_asm!(
90 {entrypoint}:
91 call {sample_scalars}
93 push {scalar_read_index(ChallengeId::CompressProgramDigestIndeterminate)}
96 read_mem {EXTENSION_DEGREE}
97 pop 1
98 dup 7
100 dup 7
101 dup 7
102 dup 7
103 dup 7
104 call {compute_compressed_digest}
107 push {scalar_write_index(ChallengeId::CompressedProgramDigest)}
111 write_mem {EXTENSION_DEGREE}
112 pop 1
113 pop 5
115 push {scalar_read_index(ChallengeId::LookupTablePublicIndeterminate)}
119 read_mem {EXTENSION_DEGREE}
120 pop 1
121 call {calculate_lookup_terminal}
124 push {scalar_write_index(ChallengeId::LookupTablePublicTerminal)}
128 write_mem {EXTENSION_DEGREE}
129 pop 1
130
131 push {EvalArg::default_initial().coefficients[2]}
133 push {EvalArg::default_initial().coefficients[1]}
134 push {EvalArg::default_initial().coefficients[0]}
135 push {scalar_write_index(ChallengeId::StandardInputTerminal)}
136 write_mem {EXTENSION_DEGREE}
137 pop 1
138
139 push {EvalArg::default_initial().coefficients[2]}
141 push {EvalArg::default_initial().coefficients[1]}
142 push {EvalArg::default_initial().coefficients[0]}
143 push {scalar_write_index(ChallengeId::StandardOutputTerminal)}
144 write_mem {EXTENSION_DEGREE}
145 pop 1
146 push {scalars_pointer}
149 return
152 )
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use triton_vm::challenges::Challenges;
159
160 use super::*;
161 use crate::rust_shadowing_helper_functions::array::insert_as_array;
162 use crate::test_prelude::*;
163 use crate::verifier::challenges::shared;
164
165 impl Procedure for NewEmptyInputAndOutput {
166 fn rust_shadow(
167 &self,
168 stack: &mut Vec<BFieldElement>,
169 memory: &mut std::collections::HashMap<BFieldElement, BFieldElement>,
170 _: &NonDeterminism,
171 _: &[BFieldElement],
172 sponge: &mut Option<Tip5>,
173 ) -> Vec<BFieldElement> {
174 let sponge = sponge.as_mut().expect("sponge must be initialized");
175 let program_digest = pop_encodable(stack);
176
177 let claim = Claim::new(program_digest);
178 let challenges = sponge.sample_scalars(self.num_of_fiat_shamir_challenges);
179 let challenges = Challenges::new(challenges, &claim);
180 dbg!(
181 "Rust-shadowing challenges: {}",
182 challenges.challenges.iter().join("\n")
183 );
184
185 stack.push(self.challenges_pointer);
186
187 insert_as_array(
188 self.challenges_pointer,
189 memory,
190 challenges.challenges.to_vec(),
191 );
192
193 vec![]
194 }
195
196 fn pseudorandom_initial_state(
197 &self,
198 seed: [u8; 32],
199 _: Option<BenchmarkCase>,
200 ) -> ProcedureInitialState {
201 let mut rng = StdRng::from_seed(seed);
202 let program_digest: Digest = rng.random();
203 let challenge = program_digest.0.into_iter().rev().collect_vec();
204 let stack = [self.init_stack_for_isolated_run(), challenge].concat();
205 let sponge = Tip5 {
206 state: rng.random(),
207 };
208
209 ProcedureInitialState {
210 stack,
211 sponge: Some(sponge),
212 ..Default::default()
213 }
214 }
215 }
216
217 #[test]
218 fn new_challenge_empty_input_output_pbt() {
219 const NUM_OF_CLAIM_DERIVED_CHALLENGES: usize = 4;
220 ShadowedProcedure::new(NewEmptyInputAndOutput {
221 num_of_claim_derived_challenges: NUM_OF_CLAIM_DERIVED_CHALLENGES,
222 num_of_fiat_shamir_challenges: Challenges::COUNT - NUM_OF_CLAIM_DERIVED_CHALLENGES,
223 challenges_pointer: shared::conventional_challenges_pointer(),
224 })
225 .test();
226 }
227}
228
229#[cfg(test)]
230mod benches {
231 use triton_vm::challenges::Challenges;
232
233 use super::*;
234 use crate::test_prelude::*;
235 use crate::verifier::challenges::shared;
236
237 #[test]
238 fn benchmark() {
239 const NUM_OF_CLAIM_DERIVED_CHALLENGES: usize = 4;
240 ShadowedProcedure::new(NewEmptyInputAndOutput {
241 num_of_claim_derived_challenges: 4,
242 num_of_fiat_shamir_challenges: Challenges::COUNT - NUM_OF_CLAIM_DERIVED_CHALLENGES,
243 challenges_pointer: shared::conventional_challenges_pointer(),
244 })
245 .bench();
246 }
247}