Skip to main content

sp1_core_executor/
syscall_code.rs

1//! Syscall definitions for the SP1 RISC-V zkVM.
2
3use deepsize2::DeepSizeOf;
4use enum_map::Enum;
5use serde::{Deserialize, Serialize};
6use strum::EnumIter;
7
8use crate::{events::FieldOperation, RiscvAirId};
9
10/// System Calls.
11///
12/// A system call is invoked by the the `ecall` instruction with a specific value in register t0.
13/// The syscall number is a 32-bit integer with the following little-endian layout:
14///
15/// | Byte 0 | Byte 1 | Byte 2 | Byte 3 |
16/// | ------ | ------ | ------ | ------ |
17/// |   ID   | Table  | Unused | Unused |
18///
19/// where:
20/// - Byte 0: The system call identifier.
21/// - Byte 1: Whether the handler of the system call has its own table. This is used in the CPU
22///   table to determine whether to lookup the syscall using the syscall interaction.
23/// - Byte 2: Previously, this was the number of additional cycles the syscall uses. Now, this byte
24///   is unused, as each syscall instruction increments the clock by 256 additionally.
25/// - Byte 3: Currently unused.
26#[derive(
27    Debug,
28    Copy,
29    Clone,
30    PartialEq,
31    Eq,
32    Hash,
33    EnumIter,
34    Ord,
35    PartialOrd,
36    Serialize,
37    Deserialize,
38    Enum,
39    Default,
40    DeepSizeOf,
41)]
42#[allow(non_camel_case_types)]
43#[allow(clippy::upper_case_acronyms)]
44#[repr(u32)]
45pub enum SyscallCode {
46    /// Halts the program.
47    #[default]
48    HALT = 0x00_00_00_00,
49
50    /// Write to the output buffer.
51    WRITE = 0x00_00_00_02,
52
53    /// Enter unconstrained block.
54    ENTER_UNCONSTRAINED = 0x00_00_00_03,
55
56    /// Exit unconstrained block.
57    EXIT_UNCONSTRAINED = 0x00_00_00_04,
58
59    /// Executes the `SHA_EXTEND` precompile.
60    SHA_EXTEND = 0x00_30_01_05,
61
62    /// Executes the `SHA_COMPRESS` precompile.
63    SHA_COMPRESS = 0x00_01_01_06,
64
65    /// Executes the `ED_ADD` precompile.
66    ED_ADD = 0x00_01_01_07,
67
68    /// Executes the `ED_DECOMPRESS` precompile.
69    ED_DECOMPRESS = 0x00_00_01_08,
70
71    /// Executes the `KECCAK_PERMUTE` precompile.
72    KECCAK_PERMUTE = 0x00_01_01_09,
73
74    /// Executes the `SECP256K1_ADD` precompile.
75    SECP256K1_ADD = 0x00_01_01_0A,
76
77    /// Executes the `SECP256K1_DOUBLE` precompile.
78    SECP256K1_DOUBLE = 0x00_00_01_0B,
79
80    /// Executes the `SECP256K1_DECOMPRESS` precompile.
81    SECP256K1_DECOMPRESS = 0x00_00_01_0C,
82
83    /// Executes the `BN254_ADD` precompile.
84    BN254_ADD = 0x00_01_01_0E,
85
86    /// Executes the `BN254_DOUBLE` precompile.
87    BN254_DOUBLE = 0x00_00_01_0F,
88
89    /// Executes the `COMMIT` precompile.
90    COMMIT = 0x00_00_00_10,
91
92    /// Executes the `COMMIT_DEFERRED_PROOFS` precompile.
93    COMMIT_DEFERRED_PROOFS = 0x00_00_00_1A,
94
95    /// Executes the `VERIFY_SP1_PROOF` precompile.
96    VERIFY_SP1_PROOF = 0x00_00_00_1B,
97
98    /// Executes the `BLS12381_DECOMPRESS` precompile.
99    BLS12381_DECOMPRESS = 0x00_00_01_1C,
100
101    /// Executes the `HINT_LEN` precompile.
102    HINT_LEN = 0x00_00_00_F0,
103
104    /// Executes the `HINT_READ` precompile.
105    HINT_READ = 0x00_00_00_F1,
106
107    /// Executes the `UINT256_MUL` precompile.
108    UINT256_MUL = 0x00_01_01_1D,
109
110    /// Executes the `U256XU2048_MUL` precompile.
111    U256XU2048_MUL = 0x00_01_01_2F,
112
113    /// Executes the `BLS12381_ADD` precompile.
114    BLS12381_ADD = 0x00_01_01_1E,
115
116    /// Executes the `BLS12381_DOUBLE` precompile.
117    BLS12381_DOUBLE = 0x00_00_01_1F,
118
119    /// Executes the `BLS12381_FP_ADD` precompile.
120    BLS12381_FP_ADD = 0x00_01_01_20,
121
122    /// Executes the `BLS12381_FP_SUB` precompile.
123    BLS12381_FP_SUB = 0x00_01_01_21,
124
125    /// Executes the `BLS12381_FP_MUL` precompile.
126    BLS12381_FP_MUL = 0x00_01_01_22,
127
128    /// Executes the `BLS12381_FP2_ADD` precompile.
129    BLS12381_FP2_ADD = 0x00_01_01_23,
130
131    /// Executes the `BLS12381_FP2_SUB` precompile.
132    BLS12381_FP2_SUB = 0x00_01_01_24,
133
134    /// Executes the `BLS12381_FP2_MUL` precompile.
135    BLS12381_FP2_MUL = 0x00_01_01_25,
136
137    /// Executes the `BN254_FP_ADD` precompile.
138    BN254_FP_ADD = 0x00_01_01_26,
139
140    /// Executes the `BN254_FP_SUB` precompile.
141    BN254_FP_SUB = 0x00_01_01_27,
142
143    /// Executes the `BN254_FP_MUL` precompile.
144    BN254_FP_MUL = 0x00_01_01_28,
145
146    /// Executes the `BN254_FP2_ADD` precompile.
147    BN254_FP2_ADD = 0x00_01_01_29,
148
149    /// Executes the `BN254_FP2_SUB` precompile.
150    BN254_FP2_SUB = 0x00_01_01_2A,
151
152    /// Executes the `BN254_FP2_MUL` precompile.
153    BN254_FP2_MUL = 0x00_01_01_2B,
154
155    /// Executes the `SECP256R1_ADD` precompile.
156    SECP256R1_ADD = 0x00_01_01_2C,
157
158    /// Executes the `SECP256R1_DOUBLE` precompile.
159    SECP256R1_DOUBLE = 0x00_00_01_2D,
160
161    /// Executes the `SECP256R1_DECOMPRESS` precompile.
162    SECP256R1_DECOMPRESS = 0x00_00_01_2E,
163
164    /// Executes the `UINT256_ADD_CARRY` precompile.
165    UINT256_ADD_CARRY = 0x00_01_01_30,
166
167    /// Executes the `UINT256_MUL_CARRY` precompile.
168    UINT256_MUL_CARRY = 0x00_01_01_31,
169
170    /// Executes the `MPROTECT` syscall.
171    #[allow(clippy::mistyped_literal_suffixes)]
172    MPROTECT = 0x00_00_01_32,
173
174    /// Executes the `POSEIDON2` syscall.
175    POSEIDON2 = 0x00_00_01_33,
176
177    /// Executes the `SIG_RETURN` syscall.
178    #[allow(clippy::mistyped_literal_suffixes)]
179    SIG_RETURN = 0x00_00_01_34,
180
181    /// Executes the `HINT_MPROTECT_FLUSH` syscall.
182    HINT_MPROTECT_FLUSH = 0x00_00_00_35,
183
184    /// Executes the `DUMP_ELF` syscall (debug).
185    DUMP_ELF = 0x00_00_00_40,
186
187    /// Executes the `INSERT_PROFILER_SYMBOLS` syscall (debug).
188    INSERT_PROFILER_SYMBOLS = 0x00_00_00_41,
189
190    /// Executes the `DELETE_PROFILER_SYMBOLS` syscall (debug).
191    DELETE_PROFILER_SYMBOLS = 0x00_00_00_42,
192}
193
194impl SyscallCode {
195    /// Create a [`SyscallCode`] from a u32.
196    #[must_use]
197    pub fn from_u32(value: u32) -> Self {
198        match value {
199            0x00_00_00_00 => SyscallCode::HALT,
200            0x00_00_00_02 => SyscallCode::WRITE,
201            0x00_00_00_03 => SyscallCode::ENTER_UNCONSTRAINED,
202            0x00_00_00_04 => SyscallCode::EXIT_UNCONSTRAINED,
203            0x00_30_01_05 => SyscallCode::SHA_EXTEND,
204            0x00_01_01_06 => SyscallCode::SHA_COMPRESS,
205            0x00_01_01_07 => SyscallCode::ED_ADD,
206            0x00_00_01_08 => SyscallCode::ED_DECOMPRESS,
207            0x00_01_01_09 => SyscallCode::KECCAK_PERMUTE,
208            0x00_01_01_0A => SyscallCode::SECP256K1_ADD,
209            0x00_00_01_0B => SyscallCode::SECP256K1_DOUBLE,
210            0x00_00_01_0C => SyscallCode::SECP256K1_DECOMPRESS,
211            0x00_01_01_0E => SyscallCode::BN254_ADD,
212            0x00_00_01_0F => SyscallCode::BN254_DOUBLE,
213            0x00_01_01_1E => SyscallCode::BLS12381_ADD,
214            0x00_00_01_1F => SyscallCode::BLS12381_DOUBLE,
215            0x00_00_00_10 => SyscallCode::COMMIT,
216            0x00_00_00_1A => SyscallCode::COMMIT_DEFERRED_PROOFS,
217            0x00_00_00_1B => SyscallCode::VERIFY_SP1_PROOF,
218            0x00_00_00_F0 => SyscallCode::HINT_LEN,
219            0x00_00_00_F1 => SyscallCode::HINT_READ,
220            0x00_01_01_1D => SyscallCode::UINT256_MUL,
221            0x00_01_01_2F => SyscallCode::U256XU2048_MUL,
222            0x00_01_01_20 => SyscallCode::BLS12381_FP_ADD,
223            0x00_01_01_21 => SyscallCode::BLS12381_FP_SUB,
224            0x00_01_01_22 => SyscallCode::BLS12381_FP_MUL,
225            0x00_01_01_23 => SyscallCode::BLS12381_FP2_ADD,
226            0x00_01_01_24 => SyscallCode::BLS12381_FP2_SUB,
227            0x00_01_01_25 => SyscallCode::BLS12381_FP2_MUL,
228            0x00_01_01_26 => SyscallCode::BN254_FP_ADD,
229            0x00_01_01_27 => SyscallCode::BN254_FP_SUB,
230            0x00_01_01_28 => SyscallCode::BN254_FP_MUL,
231            0x00_01_01_29 => SyscallCode::BN254_FP2_ADD,
232            0x00_01_01_2A => SyscallCode::BN254_FP2_SUB,
233            0x00_01_01_2B => SyscallCode::BN254_FP2_MUL,
234            0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS,
235            0x00_01_01_2C => SyscallCode::SECP256R1_ADD,
236            0x00_00_01_2D => SyscallCode::SECP256R1_DOUBLE,
237            0x00_00_01_2E => SyscallCode::SECP256R1_DECOMPRESS,
238            0x00_01_01_30 => SyscallCode::UINT256_ADD_CARRY,
239            0x00_01_01_31 => SyscallCode::UINT256_MUL_CARRY,
240            #[allow(clippy::mistyped_literal_suffixes)]
241            0x00_00_01_32 => SyscallCode::MPROTECT,
242            0x00_00_01_33 => SyscallCode::POSEIDON2,
243            #[allow(clippy::mistyped_literal_suffixes)]
244            0x00_00_01_34 => SyscallCode::SIG_RETURN,
245            0x00_00_00_35 => SyscallCode::HINT_MPROTECT_FLUSH,
246            0x00_00_00_40 => SyscallCode::DUMP_ELF,
247            0x00_00_00_41 => SyscallCode::INSERT_PROFILER_SYMBOLS,
248            0x00_00_00_42 => SyscallCode::DELETE_PROFILER_SYMBOLS,
249            _ => panic!("invalid syscall number: {value}"),
250        }
251    }
252
253    /// Get the system call identifier.
254    #[must_use]
255    pub fn syscall_id(self) -> u32 {
256        (self as u32).to_le_bytes()[0].into()
257    }
258
259    /// Get whether the handler of the system call has its own table.
260    #[must_use]
261    pub fn should_send(self) -> u32 {
262        (self as u32).to_le_bytes()[1].into()
263    }
264
265    /// Map a syscall to another one in order to coalesce their counts.
266    #[must_use]
267    #[allow(clippy::match_same_arms)]
268    pub fn count_map(&self) -> Self {
269        match self {
270            SyscallCode::BN254_FP_SUB => SyscallCode::BN254_FP_ADD,
271            SyscallCode::BN254_FP_MUL => SyscallCode::BN254_FP_ADD,
272            SyscallCode::BN254_FP2_SUB => SyscallCode::BN254_FP2_ADD,
273            SyscallCode::BLS12381_FP_SUB => SyscallCode::BLS12381_FP_ADD,
274            SyscallCode::BLS12381_FP_MUL => SyscallCode::BLS12381_FP_ADD,
275            SyscallCode::BLS12381_FP2_SUB => SyscallCode::BLS12381_FP2_ADD,
276            _ => *self,
277        }
278    }
279
280    /// Map a syscall to a field operation.
281    #[must_use]
282    pub fn fp_op_map(&self) -> FieldOperation {
283        match self {
284            SyscallCode::BLS12381_FP_ADD
285            | SyscallCode::BLS12381_FP2_ADD
286            | SyscallCode::BN254_FP_ADD
287            | SyscallCode::BN254_FP2_ADD => FieldOperation::Add,
288            SyscallCode::BLS12381_FP_SUB
289            | SyscallCode::BLS12381_FP2_SUB
290            | SyscallCode::BN254_FP_SUB
291            | SyscallCode::BN254_FP2_SUB => FieldOperation::Sub,
292            SyscallCode::BLS12381_FP_MUL
293            | SyscallCode::BLS12381_FP2_MUL
294            | SyscallCode::BN254_FP_MUL
295            | SyscallCode::BN254_FP2_MUL => FieldOperation::Mul,
296            _ => unreachable!(),
297        }
298    }
299
300    /// Map a syscall to a uint256 operation.
301    #[must_use]
302    pub fn uint256_op_map(&self) -> crate::events::Uint256Operation {
303        match self {
304            SyscallCode::UINT256_ADD_CARRY => crate::events::Uint256Operation::Add,
305            SyscallCode::UINT256_MUL_CARRY => crate::events::Uint256Operation::Mul,
306            _ => unreachable!(),
307        }
308    }
309
310    /// Get the ID of the AIR used in the syscall implementation, dispatching based on
311    /// whether untrusted programs are enabled.
312    #[must_use]
313    pub fn as_air_id_flag(self, enable_untrusted_programs: bool) -> Option<RiscvAirId> {
314        if enable_untrusted_programs {
315            return self.as_air_id_user();
316        }
317        self.as_air_id()
318    }
319
320    /// Get the ID of the AIR used in the syscall implementation.
321    #[must_use]
322    pub fn as_air_id(self) -> Option<RiscvAirId> {
323        Some(match self {
324            SyscallCode::SHA_EXTEND => RiscvAirId::ShaExtend,
325            SyscallCode::SHA_COMPRESS => RiscvAirId::ShaCompress,
326            SyscallCode::ED_ADD => RiscvAirId::EdAddAssign,
327            SyscallCode::ED_DECOMPRESS => RiscvAirId::EdDecompress,
328            SyscallCode::KECCAK_PERMUTE => RiscvAirId::KeccakPermute,
329            SyscallCode::SECP256K1_ADD => RiscvAirId::Secp256k1AddAssign,
330            SyscallCode::SECP256K1_DOUBLE => RiscvAirId::Secp256k1DoubleAssign,
331            SyscallCode::BN254_ADD => RiscvAirId::Bn254AddAssign,
332            SyscallCode::BN254_DOUBLE => RiscvAirId::Bn254DoubleAssign,
333            SyscallCode::UINT256_MUL => RiscvAirId::Uint256MulMod,
334            SyscallCode::BLS12381_ADD => RiscvAirId::Bls12381AddAssign,
335            SyscallCode::BLS12381_DOUBLE => RiscvAirId::Bls12381DoubleAssign,
336            SyscallCode::BLS12381_FP_ADD
337            | SyscallCode::BLS12381_FP_SUB
338            | SyscallCode::BLS12381_FP_MUL => RiscvAirId::Bls12381FpOpAssign,
339            SyscallCode::BLS12381_FP2_ADD | SyscallCode::BLS12381_FP2_SUB => {
340                RiscvAirId::Bls12381Fp2AddSubAssign
341            }
342            SyscallCode::BLS12381_FP2_MUL => RiscvAirId::Bls12381Fp2MulAssign,
343            SyscallCode::BN254_FP_ADD | SyscallCode::BN254_FP_SUB | SyscallCode::BN254_FP_MUL => {
344                RiscvAirId::Bn254FpOpAssign
345            }
346            SyscallCode::BN254_FP2_ADD | SyscallCode::BN254_FP2_SUB => {
347                RiscvAirId::Bn254Fp2AddSubAssign
348            }
349            SyscallCode::BN254_FP2_MUL => RiscvAirId::Bn254Fp2MulAssign,
350            SyscallCode::SECP256R1_ADD => RiscvAirId::Secp256r1AddAssign,
351            SyscallCode::SECP256R1_DOUBLE => RiscvAirId::Secp256r1DoubleAssign,
352            SyscallCode::UINT256_ADD_CARRY | SyscallCode::UINT256_MUL_CARRY => {
353                RiscvAirId::Uint256Ops
354            }
355            SyscallCode::MPROTECT => RiscvAirId::Mprotect,
356            SyscallCode::POSEIDON2 => RiscvAirId::Poseidon2,
357            SyscallCode::SIG_RETURN => RiscvAirId::SigReturn,
358            SyscallCode::HINT_MPROTECT_FLUSH
359            | SyscallCode::DUMP_ELF
360            | SyscallCode::INSERT_PROFILER_SYMBOLS
361            | SyscallCode::DELETE_PROFILER_SYMBOLS
362            | SyscallCode::U256XU2048_MUL
363            | SyscallCode::SECP256K1_DECOMPRESS
364            | SyscallCode::BLS12381_DECOMPRESS
365            | SyscallCode::SECP256R1_DECOMPRESS
366            | SyscallCode::HALT
367            | SyscallCode::WRITE
368            | SyscallCode::ENTER_UNCONSTRAINED
369            | SyscallCode::EXIT_UNCONSTRAINED
370            | SyscallCode::COMMIT
371            | SyscallCode::COMMIT_DEFERRED_PROOFS
372            | SyscallCode::VERIFY_SP1_PROOF
373            | SyscallCode::HINT_LEN
374            | SyscallCode::HINT_READ => return None,
375        })
376    }
377
378    /// Get the ID of the AIR used in the syscall implementation in user mode.
379    #[must_use]
380    pub fn as_air_id_user(self) -> Option<RiscvAirId> {
381        Some(match self {
382            SyscallCode::SHA_EXTEND => RiscvAirId::ShaExtend,
383            SyscallCode::SHA_COMPRESS => RiscvAirId::ShaCompress,
384            SyscallCode::ED_ADD => RiscvAirId::EdAddAssignUser,
385            SyscallCode::ED_DECOMPRESS => RiscvAirId::EdDecompressUser,
386            SyscallCode::KECCAK_PERMUTE => RiscvAirId::KeccakPermute,
387            SyscallCode::SECP256K1_ADD => RiscvAirId::Secp256k1AddAssignUser,
388            SyscallCode::SECP256K1_DOUBLE => RiscvAirId::Secp256k1DoubleAssignUser,
389            SyscallCode::BN254_ADD => RiscvAirId::Bn254AddAssignUser,
390            SyscallCode::BN254_DOUBLE => RiscvAirId::Bn254DoubleAssignUser,
391            SyscallCode::UINT256_MUL => RiscvAirId::Uint256MulModUser,
392            SyscallCode::BLS12381_ADD => RiscvAirId::Bls12381AddAssignUser,
393            SyscallCode::BLS12381_DOUBLE => RiscvAirId::Bls12381DoubleAssignUser,
394            SyscallCode::BLS12381_FP_ADD
395            | SyscallCode::BLS12381_FP_SUB
396            | SyscallCode::BLS12381_FP_MUL => RiscvAirId::Bls12381FpOpAssignUser,
397            SyscallCode::BLS12381_FP2_ADD | SyscallCode::BLS12381_FP2_SUB => {
398                RiscvAirId::Bls12381Fp2AddSubAssignUser
399            }
400            SyscallCode::BLS12381_FP2_MUL => RiscvAirId::Bls12381Fp2MulAssignUser,
401            SyscallCode::BN254_FP_ADD | SyscallCode::BN254_FP_SUB | SyscallCode::BN254_FP_MUL => {
402                RiscvAirId::Bn254FpOpAssignUser
403            }
404            SyscallCode::BN254_FP2_ADD | SyscallCode::BN254_FP2_SUB => {
405                RiscvAirId::Bn254Fp2AddSubAssignUser
406            }
407            SyscallCode::BN254_FP2_MUL => RiscvAirId::Bn254Fp2MulAssignUser,
408            SyscallCode::SECP256R1_ADD => RiscvAirId::Secp256r1AddAssignUser,
409            SyscallCode::SECP256R1_DOUBLE => RiscvAirId::Secp256r1DoubleAssignUser,
410            SyscallCode::UINT256_ADD_CARRY | SyscallCode::UINT256_MUL_CARRY => {
411                RiscvAirId::Uint256OpsUser
412            }
413            SyscallCode::MPROTECT => RiscvAirId::Mprotect,
414            SyscallCode::SIG_RETURN => RiscvAirId::SigReturn,
415            SyscallCode::POSEIDON2 => RiscvAirId::Poseidon2User,
416            SyscallCode::HINT_MPROTECT_FLUSH
417            | SyscallCode::DUMP_ELF
418            | SyscallCode::INSERT_PROFILER_SYMBOLS
419            | SyscallCode::DELETE_PROFILER_SYMBOLS
420            | SyscallCode::U256XU2048_MUL
421            | SyscallCode::SECP256K1_DECOMPRESS
422            | SyscallCode::BLS12381_DECOMPRESS
423            | SyscallCode::SECP256R1_DECOMPRESS
424            | SyscallCode::HALT
425            | SyscallCode::WRITE
426            | SyscallCode::ENTER_UNCONSTRAINED
427            | SyscallCode::EXIT_UNCONSTRAINED
428            | SyscallCode::COMMIT
429            | SyscallCode::COMMIT_DEFERRED_PROOFS
430            | SyscallCode::VERIFY_SP1_PROOF
431            | SyscallCode::HINT_LEN
432            | SyscallCode::HINT_READ => return None,
433        })
434    }
435
436    /// The maximum number of touched words for each syscall code.
437    #[must_use]
438    #[allow(clippy::match_same_arms)]
439    pub fn touched_addresses(&self) -> usize {
440        // To get this number, either analyze the number of touched memory in the executor of the
441        // syscall, or run a program with the syscall and analyze the ratio of heights of the
442        // `MemoryLocal` table and the corresponding syscall table in the precompile shard.
443        match self {
444            SyscallCode::SHA_EXTEND => 64,
445            SyscallCode::SHA_COMPRESS => 72,
446            SyscallCode::KECCAK_PERMUTE => 25,
447            SyscallCode::BLS12381_ADD
448            | SyscallCode::BLS12381_FP2_ADD
449            | SyscallCode::BLS12381_FP2_SUB
450            | SyscallCode::BLS12381_FP2_MUL => 24,
451            SyscallCode::BLS12381_DECOMPRESS
452            | SyscallCode::BLS12381_DOUBLE
453            | SyscallCode::BLS12381_FP_ADD
454            | SyscallCode::BLS12381_FP_SUB
455            | SyscallCode::BLS12381_FP_MUL => 12,
456            SyscallCode::ED_ADD
457            | SyscallCode::SECP256K1_ADD
458            | SyscallCode::SECP256R1_ADD
459            | SyscallCode::BN254_ADD
460            | SyscallCode::BN254_FP2_ADD
461            | SyscallCode::BN254_FP2_SUB
462            | SyscallCode::BN254_FP2_MUL => 16,
463            SyscallCode::ED_DECOMPRESS
464            | SyscallCode::SECP256K1_DECOMPRESS
465            | SyscallCode::SECP256R1_DECOMPRESS
466            | SyscallCode::SECP256K1_DOUBLE
467            | SyscallCode::SECP256R1_DOUBLE
468            | SyscallCode::BN254_DOUBLE
469            | SyscallCode::BN254_FP_ADD
470            | SyscallCode::BN254_FP_SUB
471            | SyscallCode::BN254_FP_MUL => 8,
472            SyscallCode::UINT256_MUL => 12,
473            SyscallCode::UINT256_ADD_CARRY | SyscallCode::UINT256_MUL_CARRY => 20,
474            SyscallCode::U256XU2048_MUL => 72,
475            SyscallCode::MPROTECT => 0,
476            SyscallCode::POSEIDON2 => 8,
477            _ => 0,
478        }
479    }
480
481    /// The maximum number of touched pages for each syscall code.
482    #[must_use]
483    #[allow(clippy::match_same_arms)]
484    pub fn touched_pages(&self) -> usize {
485        // To get this number, either analyze the number of touched pages in the executor of the
486        // syscall, or check the number of `AddressSlicePageProtOperation` in the corresponding AIR.
487        // This function assumes that each slice touches two pages, which is the maximum.
488        match self {
489            SyscallCode::SHA_EXTEND => 2 * 2,
490            SyscallCode::SHA_COMPRESS => 3 * 2,
491            SyscallCode::KECCAK_PERMUTE => 2 * 2,
492            SyscallCode::BLS12381_ADD
493            | SyscallCode::SECP256K1_ADD
494            | SyscallCode::SECP256R1_ADD
495            | SyscallCode::BN254_ADD
496            | SyscallCode::ED_ADD
497            | SyscallCode::BLS12381_DECOMPRESS
498            | SyscallCode::SECP256K1_DECOMPRESS
499            | SyscallCode::SECP256R1_DECOMPRESS
500            | SyscallCode::ED_DECOMPRESS => 2 * 2,
501
502            SyscallCode::BLS12381_DOUBLE
503            | SyscallCode::SECP256K1_DOUBLE
504            | SyscallCode::SECP256R1_DOUBLE
505            | SyscallCode::BN254_DOUBLE => 2,
506
507            SyscallCode::BLS12381_FP2_ADD
508            | SyscallCode::BLS12381_FP2_SUB
509            | SyscallCode::BLS12381_FP2_MUL
510            | SyscallCode::BLS12381_FP_ADD
511            | SyscallCode::BLS12381_FP_SUB
512            | SyscallCode::BLS12381_FP_MUL
513            | SyscallCode::BN254_FP2_ADD
514            | SyscallCode::BN254_FP2_SUB
515            | SyscallCode::BN254_FP2_MUL
516            | SyscallCode::BN254_FP_ADD
517            | SyscallCode::BN254_FP_SUB
518            | SyscallCode::BN254_FP_MUL => 2 * 2,
519
520            SyscallCode::UINT256_MUL => 2 * 2,
521            SyscallCode::UINT256_ADD_CARRY | SyscallCode::UINT256_MUL_CARRY => 5 * 2,
522            SyscallCode::U256XU2048_MUL => 4 * 2,
523            SyscallCode::MPROTECT => 1,
524            SyscallCode::POSEIDON2 => 2,
525            _ => 0,
526        }
527    }
528}
529
530impl std::fmt::Display for SyscallCode {
531    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
532        write!(f, "{self:?}")
533    }
534}