Skip to main content

sp1_hypercube/lookup/
interaction.rs

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/// An interaction for a lookup or a permutation argument.
12#[derive(Clone)]
13pub struct Interaction<F: Field> {
14    /// The values of the interaction.
15    pub values: Vec<VirtualPairCol<F>>,
16    /// The multiplicity of the interaction.
17    pub multiplicity: VirtualPairCol<F>,
18    /// The kind of interaction.
19    pub kind: InteractionKind,
20    /// The scope of the interaction.
21    pub scope: InteractionScope,
22}
23
24/// The type of interaction for a lookup argument.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
26pub enum InteractionKind {
27    /// Interaction with the memory table, such as read and write.
28    Memory = 1,
29
30    /// Interaction with the program table, loading an instruction at a given pc address.
31    Program = 2,
32
33    /// Interaction with the byte lookup table for byte operations.
34    Byte = 5,
35
36    /// Interaction with the current CPU state.
37    State = 7,
38
39    /// Interaction with a syscall.
40    Syscall = 8,
41
42    /// Interaction with the global table.
43    Global = 9,
44
45    /// Interaction with the `ShaExtend` chip.
46    ShaExtend = 10,
47
48    /// Interaction with the `ShaCompress` chip.
49    ShaCompress = 11,
50
51    /// Interaction with the `Keccak` chip.
52    Keccak = 12,
53
54    /// Interaction to accumulate the global interaction digests.
55    GlobalAccumulation = 13,
56
57    /// Interaction with the `MemoryGlobalInit` chip.
58    MemoryGlobalInitControl = 14,
59
60    /// Interaction with the `MemoryGlobalFinalize` chip.
61    MemoryGlobalFinalizeControl = 15,
62
63    /// Interaction with the instruction fetch table.
64    InstructionFetch = 16,
65
66    /// Interaction with the instruction decode table.
67    InstructionDecode = 17,
68
69    /// Interaction with the page prot chip.
70    PageProt = 18,
71
72    /// Interaction with the page prot chip.
73    PageProtAccess = 19,
74
75    /// Interaction with the `PageProtGlobalInit` chip.
76    PageProtGlobalInitControl = 20,
77
78    /// Interaction with the `PageProtGlobalFinalize` chip.
79    PageProtGlobalFinalizeControl = 21,
80}
81
82impl InteractionKind {
83    /// Returns all kinds of interactions.
84    #[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    /// The number of `values` sent and received for each interaction kind.
110    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    /// Whether this interaction kind gets used in `eval_public_values`.
140    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    /// Create a new interaction.
156    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    /// The index of the argument in the lookup table.
166    pub const fn argument_index(&self) -> usize {
167        self.kind as usize
168    }
169
170    /// Calculate the interactions evaluation.
171    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}