tasm_lib/verifier/vm_proof_iter/
drop.rs1use triton_vm::prelude::*;
2
3use crate::prelude::*;
4use crate::verifier::vm_proof_iter::shared::vm_proof_iter_type;
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
11pub struct Drop;
12
13impl BasicSnippet for Drop {
14 fn parameters(&self) -> Vec<(DataType, String)> {
15 vec![(
16 DataType::StructRef(vm_proof_iter_type()),
17 "vm_proof_iter".to_owned(),
18 )]
19 }
20
21 fn return_values(&self) -> Vec<(DataType, String)> {
22 vec![]
23 }
24
25 fn entrypoint(&self) -> String {
26 "tasmlib_verifier_vm_proof_iter_drop".to_owned()
27 }
28
29 fn code(&self, _library: &mut Library) -> Vec<LabelledInstruction> {
30 let entrypoint = self.entrypoint();
31
32 triton_asm!(
33 {entrypoint}:
34 addi 4
38 read_mem 5
39 pop 1
40
41 place 2
44 add
47 addi 1
48 eq
49 assert error_id 50
52 eq
55 assert error_id 60
56 return
59 )
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use arbitrary::Arbitrary;
66 use arbitrary::Unstructured;
67 use triton_vm::proof_item::ProofItemVariant;
68 use triton_vm::proof_stream::ProofStream;
69
70 use super::*;
71 use crate::test_prelude::*;
72 use crate::verifier::vm_proof_iter::dequeue_next_as::DequeueNextAs;
73 use crate::verifier::vm_proof_iter::shared::vm_proof_iter_struct::VmProofIter;
74
75 #[macro_rules_attr::apply(test)]
76 fn rust_shadow() {
77 ShadowedAccessor::new(Drop).test();
78 }
79
80 #[macro_rules_attr::apply(test)]
81 fn negative_test_proof_len_mismatch() {
82 let proof_ptr = bfe!(450);
83 let proof_len = 10_000u32;
84 let correct_proof_end = proof_ptr + bfe!(proof_len);
85 let bad_proof_length = VmProofIter {
86 current_item_count: 12,
87 total_item_count: 12,
88 proof_start_pointer: proof_ptr,
89 proof_length: proof_len,
90 current_item_pointer: correct_proof_end + bfe!(4),
91 };
92
93 test_assertion_failure(
94 &ShadowedAccessor::new(Drop),
95 Drop.init_state(bad_proof_length).into(),
96 &[50],
97 );
98 }
99
100 #[macro_rules_attr::apply(test)]
101 fn negative_test_proof_item_count_mismatch() {
102 let proof_ptr = bfe!(450);
103 let proof_len = 10_000u32;
104 let correct_proof_end = proof_ptr + bfe!(proof_len);
105 let bad_proof_length = VmProofIter {
106 current_item_count: 16,
107 total_item_count: 12,
108 proof_start_pointer: proof_ptr,
109 proof_length: proof_len,
110 current_item_pointer: correct_proof_end,
111 };
112
113 test_assertion_failure(
114 &ShadowedAccessor::new(Drop),
115 Drop.init_state(bad_proof_length).into(),
116 &[50],
117 );
118 }
119
120 impl Drop {
121 fn init_state(&self, vm_proof_iter: VmProofIter) -> AccessorInitialState {
122 let mut memory = HashMap::default();
123 let vm_iter_ptr = bfe!(1u64 << 32);
124 encode_to_memory(&mut memory, vm_iter_ptr, &vm_proof_iter);
125
126 let stack = [self.init_stack_for_isolated_run(), vec![vm_iter_ptr]].concat();
127 AccessorInitialState { stack, memory }
128 }
129 }
130
131 impl Accessor for Drop {
132 fn rust_shadow(
133 &self,
134 stack: &mut Vec<BFieldElement>,
135 memory: &HashMap<BFieldElement, BFieldElement>,
136 ) -> Result<(), RustShadowError> {
137 let vm_proof_iter_ptr = stack.pop().ok_or(RustShadowError::StackUnderflow)?;
138 let vm_proof_iter = *VmProofIter::decode_from_memory(memory, vm_proof_iter_ptr)
139 .map_err(|_| RustShadowError::DecodingError)?;
140 if vm_proof_iter.current_item_count != vm_proof_iter.total_item_count {
141 return Err(RustShadowError::InvalidProof);
142 }
143
144 if vm_proof_iter.proof_start_pointer + bfe!(vm_proof_iter.proof_length + 1)
145 != vm_proof_iter.current_item_pointer
146 {
147 return Err(RustShadowError::InvalidProof);
148 }
149
150 Ok(())
151 }
152
153 fn pseudorandom_initial_state(
154 &self,
155 seed: [u8; 32],
156 bench_case: Option<BenchmarkCase>,
157 ) -> AccessorInitialState {
158 let mut rng = StdRng::from_seed(seed);
159
160 let fake_proof_stream = match bench_case {
161 Some(BenchmarkCase::CommonCase) => {
162 let proof_item_variants = vec![ProofItemVariant::MerkleRoot; 20];
163 DequeueNextAs::pseudorandom_proof_stream(proof_item_variants, seed)
164 }
165 Some(BenchmarkCase::WorstCase) => {
166 let proof_item_variants = vec![ProofItemVariant::MerkleRoot; 40];
167 DequeueNextAs::pseudorandom_proof_stream(proof_item_variants, seed)
168 }
169 None => {
170 let bigger_seed: Vec<u8> = (0..1_000_000).map(|_| rng.random()).collect();
171 let unstructured = Unstructured::new(bigger_seed.as_ref());
172 ProofStream::arbitrary_take_rest(unstructured).unwrap()
173 }
174 };
175
176 let proof_ptr = bfe!(rng.random_range(0..20u32));
177 let fake_proof = fake_proof_stream.clone().into();
178
179 let mut vm_proof_iter = VmProofIter::new(proof_ptr, &fake_proof);
181 vm_proof_iter.current_item_count = fake_proof_stream.items.len().try_into().unwrap();
182 vm_proof_iter.current_item_pointer = proof_ptr + bfe!(fake_proof.0.len() as u64 + 2);
183
184 self.init_state(vm_proof_iter)
185 }
186 }
187}
188
189#[cfg(test)]
190mod benches {
191 use super::*;
192 use crate::test_prelude::*;
193
194 #[macro_rules_attr::apply(test)]
195 fn benchmark() {
196 ShadowedAccessor::new(Drop).bench();
197 }
198}