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