sp1_core_executor/syscalls/
code.rs

1use enum_map::Enum;
2use serde::{Deserialize, Serialize};
3use strum_macros::EnumIter;
4
5use crate::RiscvAirId;
6
7/// System Calls.
8///
9/// A system call is invoked by the the `ecall` instruction with a specific value in register t0.
10/// The syscall number is a 32-bit integer with the following little-endian layout:
11///
12/// | Byte 0 | Byte 1 | Byte 2 | Byte 3 |
13/// | ------ | ------ | ------ | ------ |
14/// |   ID   | Table  | Cycles | Unused |
15///
16/// where:
17/// - Byte 0: The system call identifier.
18/// - Byte 1: Whether the handler of the system call has its own table. This is used in the CPU
19///   table to determine whether to lookup the syscall using the syscall interaction.
20/// - Byte 2: The number of additional cycles the syscall uses. This is used to make sure the # of
21///   memory accesses is bounded.
22/// - Byte 3: Currently unused.
23#[derive(
24    Debug,
25    Copy,
26    Clone,
27    PartialEq,
28    Eq,
29    Hash,
30    EnumIter,
31    Ord,
32    PartialOrd,
33    Serialize,
34    Deserialize,
35    Enum,
36    Default,
37)]
38#[allow(non_camel_case_types)]
39#[allow(clippy::upper_case_acronyms)]
40#[repr(u32)]
41pub enum SyscallCode {
42    /// Halts the program.
43    #[default]
44    HALT = 0x00_00_00_00,
45
46    /// Write to the output buffer.
47    WRITE = 0x00_00_00_02,
48
49    /// Enter unconstrained block.
50    ENTER_UNCONSTRAINED = 0x00_00_00_03,
51
52    /// Exit unconstrained block.
53    EXIT_UNCONSTRAINED = 0x00_00_00_04,
54
55    /// Executes the `SHA_EXTEND` precompile.
56    SHA_EXTEND = 0x00_30_01_05,
57
58    /// Executes the `SHA_COMPRESS` precompile.
59    SHA_COMPRESS = 0x00_01_01_06,
60
61    /// Executes the `ED_ADD` precompile.
62    ED_ADD = 0x00_01_01_07,
63
64    /// Executes the `ED_DECOMPRESS` precompile.
65    ED_DECOMPRESS = 0x00_00_01_08,
66
67    /// Executes the `KECCAK_PERMUTE` precompile.
68    KECCAK_PERMUTE = 0x00_01_01_09,
69
70    /// Executes the `SECP256K1_ADD` precompile.
71    SECP256K1_ADD = 0x00_01_01_0A,
72
73    /// Executes the `SECP256K1_DOUBLE` precompile.
74    SECP256K1_DOUBLE = 0x00_00_01_0B,
75
76    /// Executes the `SECP256K1_DECOMPRESS` precompile.
77    SECP256K1_DECOMPRESS = 0x00_00_01_0C,
78
79    /// Executes the `BN254_ADD` precompile.
80    BN254_ADD = 0x00_01_01_0E,
81
82    /// Executes the `BN254_DOUBLE` precompile.
83    BN254_DOUBLE = 0x00_00_01_0F,
84
85    /// Executes the `COMMIT` precompile.
86    COMMIT = 0x00_00_00_10,
87
88    /// Executes the `COMMIT_DEFERRED_PROOFS` precompile.
89    COMMIT_DEFERRED_PROOFS = 0x00_00_00_1A,
90
91    /// Executes the `VERIFY_SP1_PROOF` precompile.
92    VERIFY_SP1_PROOF = 0x00_00_00_1B,
93
94    /// Executes the `BLS12381_DECOMPRESS` precompile.
95    BLS12381_DECOMPRESS = 0x00_00_01_1C,
96
97    /// Executes the `HINT_LEN` precompile.
98    HINT_LEN = 0x00_00_00_F0,
99
100    /// Executes the `HINT_READ` precompile.
101    HINT_READ = 0x00_00_00_F1,
102
103    /// Executes the `UINT256_MUL` precompile.
104    UINT256_MUL = 0x00_01_01_1D,
105
106    /// Executes the `U256XU2048_MUL` precompile.
107    U256XU2048_MUL = 0x00_01_01_2F,
108
109    /// Executes the `BLS12381_ADD` precompile.
110    BLS12381_ADD = 0x00_01_01_1E,
111
112    /// Executes the `BLS12381_DOUBLE` precompile.
113    BLS12381_DOUBLE = 0x00_00_01_1F,
114
115    /// Executes the `BLS12381_FP_ADD` precompile.
116    BLS12381_FP_ADD = 0x00_01_01_20,
117
118    /// Executes the `BLS12381_FP_SUB` precompile.
119    BLS12381_FP_SUB = 0x00_01_01_21,
120
121    /// Executes the `BLS12381_FP_MUL` precompile.
122    BLS12381_FP_MUL = 0x00_01_01_22,
123
124    /// Executes the `BLS12381_FP2_ADD` precompile.
125    BLS12381_FP2_ADD = 0x00_01_01_23,
126
127    /// Executes the `BLS12381_FP2_SUB` precompile.
128    BLS12381_FP2_SUB = 0x00_01_01_24,
129
130    /// Executes the `BLS12381_FP2_MUL` precompile.
131    BLS12381_FP2_MUL = 0x00_01_01_25,
132
133    /// Executes the `BN254_FP_ADD` precompile.
134    BN254_FP_ADD = 0x00_01_01_26,
135
136    /// Executes the `BN254_FP_SUB` precompile.
137    BN254_FP_SUB = 0x00_01_01_27,
138
139    /// Executes the `BN254_FP_MUL` precompile.
140    BN254_FP_MUL = 0x00_01_01_28,
141
142    /// Executes the `BN254_FP2_ADD` precompile.
143    BN254_FP2_ADD = 0x00_01_01_29,
144
145    /// Executes the `BN254_FP2_SUB` precompile.
146    BN254_FP2_SUB = 0x00_01_01_2A,
147
148    /// Executes the `BN254_FP2_MUL` precompile.
149    BN254_FP2_MUL = 0x00_01_01_2B,
150
151    /// Executes the `SECP256R1_ADD` precompile.
152    SECP256R1_ADD = 0x00_01_01_2C,
153
154    /// Executes the `SECP256R1_DOUBLE` precompile.
155    SECP256R1_DOUBLE = 0x00_00_01_2D,
156
157    /// Executes the `SECP256R1_DECOMPRESS` precompile.
158    SECP256R1_DECOMPRESS = 0x00_00_01_2E,
159}
160
161impl SyscallCode {
162    /// Create a [`SyscallCode`] from a u32.
163    #[must_use]
164    pub fn from_u32(value: u32) -> Self {
165        match value {
166            0x00_00_00_00 => SyscallCode::HALT,
167            0x00_00_00_02 => SyscallCode::WRITE,
168            0x00_00_00_03 => SyscallCode::ENTER_UNCONSTRAINED,
169            0x00_00_00_04 => SyscallCode::EXIT_UNCONSTRAINED,
170            0x00_30_01_05 => SyscallCode::SHA_EXTEND,
171            0x00_01_01_06 => SyscallCode::SHA_COMPRESS,
172            0x00_01_01_07 => SyscallCode::ED_ADD,
173            0x00_00_01_08 => SyscallCode::ED_DECOMPRESS,
174            0x00_01_01_09 => SyscallCode::KECCAK_PERMUTE,
175            0x00_01_01_0A => SyscallCode::SECP256K1_ADD,
176            0x00_00_01_0B => SyscallCode::SECP256K1_DOUBLE,
177            0x00_00_01_0C => SyscallCode::SECP256K1_DECOMPRESS,
178            0x00_01_01_0E => SyscallCode::BN254_ADD,
179            0x00_00_01_0F => SyscallCode::BN254_DOUBLE,
180            0x00_01_01_1E => SyscallCode::BLS12381_ADD,
181            0x00_00_01_1F => SyscallCode::BLS12381_DOUBLE,
182            0x00_00_00_10 => SyscallCode::COMMIT,
183            0x00_00_00_1A => SyscallCode::COMMIT_DEFERRED_PROOFS,
184            0x00_00_00_1B => SyscallCode::VERIFY_SP1_PROOF,
185            0x00_00_00_F0 => SyscallCode::HINT_LEN,
186            0x00_00_00_F1 => SyscallCode::HINT_READ,
187            0x00_01_01_1D => SyscallCode::UINT256_MUL,
188            0x00_01_01_2F => SyscallCode::U256XU2048_MUL,
189            0x00_01_01_20 => SyscallCode::BLS12381_FP_ADD,
190            0x00_01_01_21 => SyscallCode::BLS12381_FP_SUB,
191            0x00_01_01_22 => SyscallCode::BLS12381_FP_MUL,
192            0x00_01_01_23 => SyscallCode::BLS12381_FP2_ADD,
193            0x00_01_01_24 => SyscallCode::BLS12381_FP2_SUB,
194            0x00_01_01_25 => SyscallCode::BLS12381_FP2_MUL,
195            0x00_01_01_26 => SyscallCode::BN254_FP_ADD,
196            0x00_01_01_27 => SyscallCode::BN254_FP_SUB,
197            0x00_01_01_28 => SyscallCode::BN254_FP_MUL,
198            0x00_01_01_29 => SyscallCode::BN254_FP2_ADD,
199            0x00_01_01_2A => SyscallCode::BN254_FP2_SUB,
200            0x00_01_01_2B => SyscallCode::BN254_FP2_MUL,
201            0x00_00_01_1C => SyscallCode::BLS12381_DECOMPRESS,
202            0x00_01_01_2C => SyscallCode::SECP256R1_ADD,
203            0x00_00_01_2D => SyscallCode::SECP256R1_DOUBLE,
204            0x00_00_01_2E => SyscallCode::SECP256R1_DECOMPRESS,
205            _ => panic!("invalid syscall number: {value}"),
206        }
207    }
208
209    /// Get the system call identifier.
210    #[must_use]
211    pub fn syscall_id(self) -> u32 {
212        (self as u32).to_le_bytes()[0].into()
213    }
214
215    /// Get whether the handler of the system call has its own table.
216    #[must_use]
217    pub fn should_send(self) -> u32 {
218        (self as u32).to_le_bytes()[1].into()
219    }
220
221    /// Get the number of additional cycles the syscall uses.
222    #[must_use]
223    pub fn num_cycles(self) -> u32 {
224        (self as u32).to_le_bytes()[2].into()
225    }
226
227    /// Map a syscall to another one in order to coalesce their counts.
228    #[must_use]
229    #[allow(clippy::match_same_arms)]
230    pub fn count_map(&self) -> Self {
231        match self {
232            SyscallCode::BN254_FP_SUB => SyscallCode::BN254_FP_ADD,
233            SyscallCode::BN254_FP_MUL => SyscallCode::BN254_FP_ADD,
234            SyscallCode::BN254_FP2_SUB => SyscallCode::BN254_FP2_ADD,
235            SyscallCode::BLS12381_FP_SUB => SyscallCode::BLS12381_FP_ADD,
236            SyscallCode::BLS12381_FP_MUL => SyscallCode::BLS12381_FP_ADD,
237            SyscallCode::BLS12381_FP2_SUB => SyscallCode::BLS12381_FP2_ADD,
238            _ => *self,
239        }
240    }
241
242    /// Get the ID of the AIR used in the syscall implementation.
243    #[must_use]
244    pub fn as_air_id(self) -> Option<RiscvAirId> {
245        Some(match self {
246            SyscallCode::SHA_EXTEND => RiscvAirId::ShaExtend,
247            SyscallCode::SHA_COMPRESS => RiscvAirId::ShaCompress,
248            SyscallCode::ED_ADD => RiscvAirId::EdAddAssign,
249            SyscallCode::ED_DECOMPRESS => RiscvAirId::EdDecompress,
250            SyscallCode::KECCAK_PERMUTE => RiscvAirId::KeccakPermute,
251            SyscallCode::SECP256K1_ADD => RiscvAirId::Secp256k1AddAssign,
252            SyscallCode::SECP256K1_DOUBLE => RiscvAirId::Secp256k1DoubleAssign,
253            SyscallCode::SECP256K1_DECOMPRESS => RiscvAirId::Secp256k1Decompress,
254            SyscallCode::BN254_ADD => RiscvAirId::Bn254AddAssign,
255            SyscallCode::BN254_DOUBLE => RiscvAirId::Bn254DoubleAssign,
256            SyscallCode::BLS12381_DECOMPRESS => RiscvAirId::Bls12381Decompress,
257            SyscallCode::UINT256_MUL => RiscvAirId::Uint256MulMod,
258            SyscallCode::U256XU2048_MUL => RiscvAirId::U256XU2048Mul,
259            SyscallCode::BLS12381_ADD => RiscvAirId::Bls12381AddAssign,
260            SyscallCode::BLS12381_DOUBLE => RiscvAirId::Bls12381DoubleAssign,
261            SyscallCode::BLS12381_FP_ADD |
262            SyscallCode::BLS12381_FP_SUB |
263            SyscallCode::BLS12381_FP_MUL => RiscvAirId::Bls12381FpOpAssign,
264            SyscallCode::BLS12381_FP2_ADD | SyscallCode::BLS12381_FP2_SUB => {
265                RiscvAirId::Bls12381Fp2AddSubAssign
266            }
267            SyscallCode::BLS12381_FP2_MUL => RiscvAirId::Bls12381Fp2MulAssign,
268            SyscallCode::BN254_FP_ADD | SyscallCode::BN254_FP_SUB | SyscallCode::BN254_FP_MUL => {
269                RiscvAirId::Bn254FpOpAssign
270            }
271            SyscallCode::BN254_FP2_ADD | SyscallCode::BN254_FP2_SUB => {
272                RiscvAirId::Bn254Fp2AddSubAssign
273            }
274            SyscallCode::BN254_FP2_MUL => RiscvAirId::Bn254Fp2MulAssign,
275            SyscallCode::SECP256R1_ADD => RiscvAirId::Secp256r1AddAssign,
276            SyscallCode::SECP256R1_DOUBLE => RiscvAirId::Secp256r1DoubleAssign,
277            SyscallCode::SECP256R1_DECOMPRESS => RiscvAirId::Secp256r1Decompress,
278            SyscallCode::HALT |
279            SyscallCode::WRITE |
280            SyscallCode::ENTER_UNCONSTRAINED |
281            SyscallCode::EXIT_UNCONSTRAINED |
282            SyscallCode::COMMIT |
283            SyscallCode::COMMIT_DEFERRED_PROOFS |
284            SyscallCode::VERIFY_SP1_PROOF |
285            SyscallCode::HINT_LEN |
286            SyscallCode::HINT_READ => return None,
287        })
288    }
289}
290
291impl std::fmt::Display for SyscallCode {
292    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293        write!(f, "{self:?}")
294    }
295}