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 | InteractionKind::Syscall => 9,
113 InteractionKind::Program => 16,
114 InteractionKind::Byte => 4,
115 InteractionKind::Global => 11,
116
117 InteractionKind::ShaCompress => 25,
118 InteractionKind::Keccak => 106,
119 InteractionKind::GlobalAccumulation => 15,
120
121 InteractionKind::InstructionFetch => 22,
122 InteractionKind::InstructionDecode => 19,
123 InteractionKind::ShaExtend
124 | InteractionKind::PageProt
125 | InteractionKind::PageProtAccess => 6,
126 InteractionKind::State
127 | InteractionKind::PageProtGlobalInitControl
128 | InteractionKind::PageProtGlobalFinalizeControl
129 | InteractionKind::MemoryGlobalInitControl
130 | InteractionKind::MemoryGlobalFinalizeControl => 5,
131 }
132 }
133
134 #[must_use]
135 pub fn appears_in_eval_public_values(&self) -> bool {
137 matches!(
138 self,
139 InteractionKind::Byte
140 | InteractionKind::State
141 | InteractionKind::MemoryGlobalFinalizeControl
142 | InteractionKind::MemoryGlobalInitControl
143 | InteractionKind::PageProtGlobalFinalizeControl
144 | InteractionKind::PageProtGlobalInitControl
145 | InteractionKind::GlobalAccumulation
146 )
147 }
148}
149
150impl<F: Field> Interaction<F> {
151 pub const fn new(
153 values: Vec<VirtualPairCol<F>>,
154 multiplicity: VirtualPairCol<F>,
155 kind: InteractionKind,
156 scope: InteractionScope,
157 ) -> Self {
158 Self { values, multiplicity, kind, scope }
159 }
160
161 pub const fn argument_index(&self) -> usize {
163 self.kind as usize
164 }
165
166 pub fn eval<Expr, Var>(
168 &self,
169 preprocessed: Option<&MleEval<Var>>,
170 main: &MleEval<Var>,
171 alpha: Expr,
172 betas: &[Expr],
173 ) -> (Expr, Expr)
174 where
175 F: Into<Expr>,
176 Expr: AbstractField + Mul<F, Output = Expr>,
177 Var: Into<Expr> + Copy,
178 {
179 let mut multiplicity_eval = self.multiplicity.constant.into();
180 for (column, weight) in self.multiplicity.column_weights.iter() {
181 let weight: Expr = (*weight).into();
182 match column {
183 PairCol::Preprocessed(i) => {
184 multiplicity_eval += preprocessed.as_ref().unwrap()[*i].into() * weight;
185 }
186 PairCol::Main(i) => multiplicity_eval += main[*i].into() * weight,
187 }
188 }
189
190 let mut betas = betas.iter().cloned();
191 let mut fingerprint_eval =
192 alpha + betas.next().unwrap() * Expr::from_canonical_usize(self.argument_index());
193 for (element, beta) in self.values.iter().zip(betas) {
194 let evaluation = if let Some(preprocessed) = preprocessed {
195 element.apply::<Expr, Var>(preprocessed, main)
196 } else {
197 element.apply::<Expr, Var>(&[], main)
198 };
199 fingerprint_eval += evaluation * beta;
200 }
201
202 (multiplicity_eval, fingerprint_eval)
203 }
204}
205
206impl<F: Field> Debug for Interaction<F> {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 f.debug_struct("Interaction")
209 .field("kind", &self.kind)
210 .field("scope", &self.scope)
211 .finish_non_exhaustive()
212 }
213}
214
215impl Display for InteractionKind {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 match self {
218 InteractionKind::Memory => write!(f, "Memory"),
219 InteractionKind::Program => write!(f, "Program"),
220 InteractionKind::Byte => write!(f, "Byte"),
221 InteractionKind::State => write!(f, "State"),
222 InteractionKind::Syscall => write!(f, "Syscall"),
223 InteractionKind::Global => write!(f, "Global"),
224 InteractionKind::ShaExtend => write!(f, "ShaExtend"),
225 InteractionKind::ShaCompress => write!(f, "ShaCompress"),
226 InteractionKind::Keccak => write!(f, "Keccak"),
227 InteractionKind::GlobalAccumulation => write!(f, "GlobalAccumulation"),
228 InteractionKind::MemoryGlobalInitControl => write!(f, "MemoryGlobalInitControl"),
229 InteractionKind::MemoryGlobalFinalizeControl => {
230 write!(f, "MemoryGlobalFinalizeControl")
231 }
232 InteractionKind::InstructionFetch => write!(f, "InstructionFetch"),
233 InteractionKind::InstructionDecode => write!(f, "InstructionDecode"),
234 InteractionKind::PageProt => write!(f, "PageProt"),
235 InteractionKind::PageProtAccess => write!(f, "PageProtAccess"),
236 InteractionKind::PageProtGlobalInitControl => write!(f, "PageProtGlobalInitControl"),
237 InteractionKind::PageProtGlobalFinalizeControl => {
238 write!(f, "PageProtGlobalFinalizeControl")
239 }
240 }
241 }
242}