tasm_lib/traits/
read_only_algorithm.rs1use std::collections::HashMap;
2use std::collections::VecDeque;
3
4use rand::prelude::*;
5use triton_vm::prelude::*;
6
7use super::basic_snippet::BasicSnippet;
8use super::rust_shadow::RustShadow;
9use crate::linker::execute_bench;
10use crate::prelude::Tip5;
11use crate::snippet_bencher::write_benchmarks;
12use crate::snippet_bencher::BenchmarkCase;
13use crate::snippet_bencher::NamedBenchmarkResult;
14use crate::test_helpers::test_rust_equivalence_given_complete_state;
15use crate::InitVmState;
16
17pub trait ReadOnlyAlgorithm: BasicSnippet {
32 fn rust_shadow(
33 &self,
34 stack: &mut Vec<BFieldElement>,
35 memory: &HashMap<BFieldElement, BFieldElement>,
36 nd_tokens: VecDeque<BFieldElement>,
37 nd_digests: VecDeque<Digest>,
38 );
39
40 fn pseudorandom_initial_state(
41 &self,
42 seed: [u8; 32],
43 bench_case: Option<BenchmarkCase>,
44 ) -> ReadOnlyAlgorithmInitialState;
45
46 fn corner_case_initial_states(&self) -> Vec<ReadOnlyAlgorithmInitialState> {
47 vec![]
48 }
49}
50
51#[derive(Debug, Clone, Default)]
52pub struct ReadOnlyAlgorithmInitialState {
53 pub stack: Vec<BFieldElement>,
54 pub nondeterminism: NonDeterminism,
55}
56
57impl From<ReadOnlyAlgorithmInitialState> for InitVmState {
58 fn from(value: ReadOnlyAlgorithmInitialState) -> Self {
59 Self {
60 stack: value.stack,
61 nondeterminism: value.nondeterminism,
62 ..Default::default()
63 }
64 }
65}
66
67pub struct ShadowedReadOnlyAlgorithm<T: ReadOnlyAlgorithm> {
68 algorithm: T,
69}
70
71impl<T: ReadOnlyAlgorithm> ShadowedReadOnlyAlgorithm<T> {
72 pub fn new(algorithm: T) -> Self {
73 Self { algorithm }
74 }
75}
76
77impl<T> RustShadow for ShadowedReadOnlyAlgorithm<T>
78where
79 T: ReadOnlyAlgorithm,
80{
81 fn inner(&self) -> &dyn BasicSnippet {
82 &self.algorithm
83 }
84
85 fn rust_shadow_wrapper(
86 &self,
87 _stdin: &[BFieldElement],
88 nondeterminism: &NonDeterminism,
89 stack: &mut Vec<BFieldElement>,
90 memory: &mut HashMap<BFieldElement, BFieldElement>,
91 _sponge: &mut Option<Tip5>,
92 ) -> Vec<BFieldElement> {
93 self.algorithm.rust_shadow(
94 stack,
95 memory,
96 nondeterminism.individual_tokens.to_owned().into(),
97 nondeterminism.digests.to_owned().into(),
98 );
99 vec![]
100 }
101
102 fn test(&self) {
103 for corner_case in self.algorithm.corner_case_initial_states() {
104 let stdin = vec![];
105 test_rust_equivalence_given_complete_state(
106 self,
107 &corner_case.stack,
108 &stdin,
109 &corner_case.nondeterminism,
110 &None,
111 None,
112 );
113 }
114
115 let num_states = 10;
116 let mut rng = StdRng::from_seed(rand::random());
117 for _ in 0..num_states {
118 let ReadOnlyAlgorithmInitialState {
119 stack,
120 nondeterminism,
121 } = self
122 .algorithm
123 .pseudorandom_initial_state(rng.random(), None);
124
125 let stdin = vec![];
126 test_rust_equivalence_given_complete_state(
127 self,
128 &stack,
129 &stdin,
130 &nondeterminism,
131 &None,
132 None,
133 );
134 }
135 }
136
137 fn bench(&self) {
138 let mut rng = StdRng::from_seed(
139 hex::decode("73a24b6b8b32e4d7d563a4d9a85f476573a24b6b8b32e4d7d563a4d9a85f4765")
140 .unwrap()
141 .try_into()
142 .unwrap(),
143 );
144 let mut benchmarks = Vec::with_capacity(2);
145
146 for bench_case in [BenchmarkCase::CommonCase, BenchmarkCase::WorstCase] {
147 let ReadOnlyAlgorithmInitialState {
148 stack,
149 nondeterminism,
150 } = self
151 .algorithm
152 .pseudorandom_initial_state(rng.random(), Some(bench_case));
153 let program = self.algorithm.link_for_isolated_run();
154 let benchmark = execute_bench(&program, &stack, vec![], nondeterminism, None);
155 let benchmark = NamedBenchmarkResult {
156 name: self.algorithm.entrypoint(),
157 benchmark_result: benchmark,
158 case: bench_case,
159 };
160 benchmarks.push(benchmark);
161 }
162
163 write_benchmarks(benchmarks);
164 }
165}