1use core::fmt::{Debug, Display};
2use std::ops::Mul;
3
4use serde::{Deserialize, Serialize};
5use slop_air::{PairCol, VirtualPairCol};
6use slop_algebra::{AbstractField, Field};
7use slop_multilinear::MleEval;
8
9use crate::air::InteractionScope;
10
11#[derive(Clone)]
13pub struct Interaction<F: Field> {
14 pub values: Vec<VirtualPairCol<F>>,
16 pub multiplicity: VirtualPairCol<F>,
18 pub kind: InteractionKind,
20 pub scope: InteractionScope,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
26pub enum InteractionKind {
27 Memory = 1,
29
30 Program = 2,
32
33 Byte = 5,
35
36 State = 7,
38
39 Syscall = 8,
41
42 Global = 9,
44
45 ShaExtend = 10,
47
48 ShaCompress = 11,
50
51 Keccak = 12,
53
54 GlobalAccumulation = 13,
56
57 MemoryGlobalInitControl = 14,
59
60 MemoryGlobalFinalizeControl = 15,
62
63 InstructionFetch = 16,
65
66 InstructionDecode = 17,
68
69 PageProt = 18,
71
72 PageProtAccess = 19,
74
75 PageProtGlobalInitControl = 20,
77
78 PageProtGlobalFinalizeControl = 21,
80}
81
82impl InteractionKind {
83 #[must_use]
85 pub fn all_kinds() -> Vec<InteractionKind> {
86 vec![
87 InteractionKind::Memory,
88 InteractionKind::Program,
89 InteractionKind::Byte,
90 InteractionKind::State,
91 InteractionKind::Syscall,
92 InteractionKind::Global,
93 InteractionKind::ShaExtend,
94 InteractionKind::ShaCompress,
95 InteractionKind::Keccak,
96 InteractionKind::GlobalAccumulation,
97 InteractionKind::MemoryGlobalInitControl,
98 InteractionKind::MemoryGlobalFinalizeControl,
99 InteractionKind::InstructionFetch,
100 InteractionKind::InstructionDecode,
101 InteractionKind::PageProtAccess,
102 InteractionKind::PageProtGlobalInitControl,
103 InteractionKind::PageProtGlobalFinalizeControl,
104 InteractionKind::PageProt,
105 ]
106 }
107
108 #[must_use]
109 pub fn num_values(&self) -> usize {
111 match self {
112 InteractionKind::Memory => 9,
113 #[cfg(feature = "mprotect")]
114 InteractionKind::Syscall => 10,
115 #[cfg(not(feature = "mprotect"))]
116 InteractionKind::Syscall => 9,
117 InteractionKind::Program => 16,
118 InteractionKind::Byte => 4,
119 InteractionKind::Global => 11,
120
121 InteractionKind::ShaCompress => 25,
122 InteractionKind::Keccak => 106,
123 InteractionKind::GlobalAccumulation => 15,
124
125 InteractionKind::InstructionFetch => 22,
126 InteractionKind::InstructionDecode => 19,
127 InteractionKind::ShaExtend
128 | InteractionKind::PageProt
129 | InteractionKind::PageProtAccess => 6,
130 InteractionKind::State
131 | InteractionKind::PageProtGlobalInitControl
132 | InteractionKind::PageProtGlobalFinalizeControl
133 | InteractionKind::MemoryGlobalInitControl
134 | InteractionKind::MemoryGlobalFinalizeControl => 5,
135 }
136 }
137
138 #[must_use]
139 pub fn appears_in_eval_public_values(&self) -> bool {
141 matches!(
142 self,
143 InteractionKind::Byte
144 | InteractionKind::State
145 | InteractionKind::MemoryGlobalFinalizeControl
146 | InteractionKind::MemoryGlobalInitControl
147 | InteractionKind::PageProtGlobalFinalizeControl
148 | InteractionKind::PageProtGlobalInitControl
149 | InteractionKind::GlobalAccumulation
150 )
151 }
152}
153
154impl<F: Field> Interaction<F> {
155 pub const fn new(
157 values: Vec<VirtualPairCol<F>>,
158 multiplicity: VirtualPairCol<F>,
159 kind: InteractionKind,
160 scope: InteractionScope,
161 ) -> Self {
162 Self { values, multiplicity, kind, scope }
163 }
164
165 pub const fn argument_index(&self) -> usize {
167 self.kind as usize
168 }
169
170 pub fn eval<Expr, Var>(
172 &self,
173 preprocessed: Option<&MleEval<Var>>,
174 main: &MleEval<Var>,
175 alpha: Expr,
176 betas: &[Expr],
177 ) -> (Expr, Expr)
178 where
179 F: Into<Expr>,
180 Expr: AbstractField + Mul<F, Output = Expr>,
181 Var: Into<Expr> + Copy,
182 {
183 let mut multiplicity_eval = self.multiplicity.constant.into();
184 for (column, weight) in self.multiplicity.column_weights.iter() {
185 let weight: Expr = (*weight).into();
186 match column {
187 PairCol::Preprocessed(i) => {
188 multiplicity_eval += preprocessed.as_ref().unwrap()[*i].into() * weight;
189 }
190 PairCol::Main(i) => multiplicity_eval += main[*i].into() * weight,
191 }
192 }
193
194 let mut betas = betas.iter().cloned();
195 let mut fingerprint_eval =
196 alpha + betas.next().unwrap() * Expr::from_canonical_usize(self.argument_index());
197 for (element, beta) in self.values.iter().zip(betas) {
198 let evaluation = if let Some(preprocessed) = preprocessed {
199 element.apply::<Expr, Var>(preprocessed, main)
200 } else {
201 element.apply::<Expr, Var>(&[], main)
202 };
203 fingerprint_eval += evaluation * beta;
204 }
205
206 (multiplicity_eval, fingerprint_eval)
207 }
208}
209
210impl<F: Field> Debug for Interaction<F> {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 f.debug_struct("Interaction")
213 .field("kind", &self.kind)
214 .field("scope", &self.scope)
215 .finish_non_exhaustive()
216 }
217}
218
219impl Display for InteractionKind {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 match self {
222 InteractionKind::Memory => write!(f, "Memory"),
223 InteractionKind::Program => write!(f, "Program"),
224 InteractionKind::Byte => write!(f, "Byte"),
225 InteractionKind::State => write!(f, "State"),
226 InteractionKind::Syscall => write!(f, "Syscall"),
227 InteractionKind::Global => write!(f, "Global"),
228 InteractionKind::ShaExtend => write!(f, "ShaExtend"),
229 InteractionKind::ShaCompress => write!(f, "ShaCompress"),
230 InteractionKind::Keccak => write!(f, "Keccak"),
231 InteractionKind::GlobalAccumulation => write!(f, "GlobalAccumulation"),
232 InteractionKind::MemoryGlobalInitControl => write!(f, "MemoryGlobalInitControl"),
233 InteractionKind::MemoryGlobalFinalizeControl => {
234 write!(f, "MemoryGlobalFinalizeControl")
235 }
236 InteractionKind::InstructionFetch => write!(f, "InstructionFetch"),
237 InteractionKind::InstructionDecode => write!(f, "InstructionDecode"),
238 InteractionKind::PageProt => write!(f, "PageProt"),
239 InteractionKind::PageProtAccess => write!(f, "PageProtAccess"),
240 InteractionKind::PageProtGlobalInitControl => write!(f, "PageProtGlobalInitControl"),
241 InteractionKind::PageProtGlobalFinalizeControl => {
242 write!(f, "PageProtGlobalFinalizeControl")
243 }
244 }
245 }
246}