Skip to main content

sp1_core_executor/
lib.rs

1//! An implementation of an exucutor for the SP1 RISC-V zkVM.
2
3#![warn(clippy::pedantic)]
4#![allow(clippy::similar_names)]
5#![allow(clippy::cast_possible_wrap)]
6#![allow(clippy::cast_possible_truncation)]
7#![allow(clippy::cast_sign_loss)]
8#![allow(clippy::module_name_repetitions)]
9#![allow(clippy::needless_range_loop)]
10#![allow(clippy::cast_lossless)]
11#![allow(clippy::bool_to_int_with_if)]
12#![allow(clippy::should_panic_without_expect)]
13#![allow(clippy::field_reassign_with_default)]
14#![allow(clippy::manual_assert)]
15#![allow(clippy::unreadable_literal)]
16#![allow(clippy::match_wildcard_for_single_variants)]
17#![allow(clippy::missing_panics_doc)]
18#![allow(clippy::missing_errors_doc)]
19#![allow(clippy::explicit_iter_loop)]
20#![allow(clippy::struct_excessive_bools)]
21#![warn(missing_docs)]
22
23// We cannot write module doc for build module, since it will be use
24// in current crate's build script via `include!`.
25#[allow(missing_docs)]
26pub mod build;
27
28mod air;
29mod context;
30mod debug;
31mod disassembler;
32mod errors;
33pub mod events;
34mod hook;
35mod instruction;
36mod tracing;
37pub use tracing::TracingVM;
38mod vm;
39pub use vm::{
40    gas::get_complexity_mapping,
41    memory::CompressedMemory,
42    results::CycleResult,
43    shapes::{MAXIMUM_CYCLE_AREA, MAXIMUM_PADDING_AREA},
44    CoreVM,
45};
46mod splicing;
47pub use splicing::{SplicedMinimalTrace, SplicingVM};
48mod estimating;
49pub use estimating::GasEstimatingVM;
50
51mod minimal;
52pub use minimal::*;
53
54mod memory;
55mod opcode;
56mod opts;
57#[cfg(feature = "profiling")]
58mod profiler;
59mod program;
60mod record;
61mod register;
62mod report;
63mod retain;
64mod state;
65pub mod subproof;
66mod syscall_code;
67pub use syscall_code::*;
68mod utils;
69
70pub use air::*;
71pub use context::*;
72pub use errors::*;
73pub use hook::*;
74pub use instruction::*;
75// pub use minimal::*;
76pub use opcode::*;
77pub use opts::*;
78pub use program::*;
79pub use record::*;
80pub use register::*;
81pub use report::*;
82pub use retain::*;
83pub use state::*;
84pub use utils::*;
85
86pub use sp1_hypercube::SP1RecursionProof;
87
88/// The default increment for the program counter. Is used for all instructions except
89/// for branches and jumps.
90pub const PC_INC: u32 = 4;
91
92/// The default increment for the timestamp.
93pub const CLK_INC: u32 = 8;
94
95/// The executor uses this PC to determine if the program has halted.
96/// As a PC, it is invalid since it is not a multiple of [`PC_INC`].
97pub const HALT_PC: u64 = 1;
98
99/// The number of rows in the `ByteChip`.
100pub const BYTE_NUM_ROWS: u64 = 1 << 16;
101
102/// The number of rows in the `RangeChip`.
103pub const RANGE_NUM_ROWS: u64 = 1 << 17;
104
105/// A module for testing programs.
106#[cfg(test)]
107pub mod programs {
108    #[allow(dead_code)]
109    #[allow(missing_docs)]
110    pub mod tests {
111        use crate::{utils::add_halt, Instruction, Opcode, Program};
112
113        pub use test_artifacts::{
114            FIBONACCI_ELF, PANIC_ELF, SECP256R1_ADD_ELF, SECP256R1_DOUBLE_ELF, SSZ_WITHDRAWALS_ELF,
115            U256XU2048_MUL_ELF,
116        };
117
118        #[must_use]
119        pub fn simple_program() -> Program {
120            let mut instructions = vec![
121                Instruction::new(Opcode::ADD, 29, 0, 5, false, true),
122                Instruction::new(Opcode::ADD, 30, 0, 37, false, true),
123                Instruction::new(Opcode::ADD, 31, 30, 29, false, false),
124            ];
125            add_halt(&mut instructions);
126            Program::new(instructions, 0, 0)
127        }
128
129        /// Get the fibonacci program.
130        ///
131        /// # Panics
132        ///
133        /// This function will panic if the program fails to load.
134        #[must_use]
135        pub fn fibonacci_program() -> Program {
136            Program::from(&FIBONACCI_ELF).unwrap()
137        }
138
139        /// Get the secp256r1 add program.
140        ///
141        /// # Panics
142        ///
143        /// This function will panic if the program fails to load.
144        #[must_use]
145        pub fn secp256r1_add_program() -> Program {
146            Program::from(&SECP256R1_ADD_ELF).unwrap()
147        }
148
149        /// Get the secp256r1 double program.
150        ///
151        /// # Panics
152        ///
153        /// This function will panic if the program fails to load.
154        #[must_use]
155        pub fn secp256r1_double_program() -> Program {
156            Program::from(&SECP256R1_DOUBLE_ELF).unwrap()
157        }
158
159        /// Get the SSZ withdrawals program.
160        ///
161        /// # Panics
162        ///
163        /// This function will panic if the program fails to load.
164        #[must_use]
165        pub fn ssz_withdrawals_program() -> Program {
166            Program::from(&SSZ_WITHDRAWALS_ELF).unwrap()
167        }
168
169        /// Get the panic program.
170        ///
171        /// # Panics
172        ///
173        /// This function will panic if the program fails to load.
174        #[must_use]
175        pub fn panic_program() -> Program {
176            Program::from(&PANIC_ELF).unwrap()
177        }
178
179        #[must_use]
180        #[allow(clippy::unreadable_literal)]
181        pub fn simple_memory_program() -> Program {
182            let mut instructions = vec![
183                Instruction::new(Opcode::ADD, 29, 0, 0x12348765, false, true),
184                // SW and LW
185                Instruction::new(Opcode::SW, 29, 0, 0x27654320, false, true),
186                Instruction::new(Opcode::LW, 28, 0, 0x27654320, false, true),
187                // LBU
188                Instruction::new(Opcode::LBU, 27, 0, 0x27654320, false, true),
189                Instruction::new(Opcode::LBU, 26, 0, 0x27654321, false, true),
190                Instruction::new(Opcode::LBU, 25, 0, 0x27654322, false, true),
191                Instruction::new(Opcode::LBU, 24, 0, 0x27654323, false, true),
192                // LB
193                Instruction::new(Opcode::LB, 23, 0, 0x27654320, false, true),
194                Instruction::new(Opcode::LB, 22, 0, 0x27654321, false, true),
195                // LHU
196                Instruction::new(Opcode::LHU, 21, 0, 0x27654320, false, true),
197                Instruction::new(Opcode::LHU, 20, 0, 0x27654322, false, true),
198                // LH
199                Instruction::new(Opcode::LH, 19, 0, 0x27654320, false, true),
200                Instruction::new(Opcode::LH, 18, 0, 0x27654322, false, true),
201                // SB
202                Instruction::new(Opcode::ADD, 17, 0, 0x38276525, false, true),
203                // Save the value 0x12348765 into address 0x43627530
204                Instruction::new(Opcode::SW, 29, 0, 0x43627530, false, true),
205                Instruction::new(Opcode::SB, 17, 0, 0x43627530, false, true),
206                Instruction::new(Opcode::LW, 16, 0, 0x43627530, false, true),
207                Instruction::new(Opcode::SB, 17, 0, 0x43627531, false, true),
208                Instruction::new(Opcode::LW, 15, 0, 0x43627530, false, true),
209                Instruction::new(Opcode::SB, 17, 0, 0x43627532, false, true),
210                Instruction::new(Opcode::LW, 14, 0, 0x43627530, false, true),
211                Instruction::new(Opcode::SB, 17, 0, 0x43627533, false, true),
212                Instruction::new(Opcode::LW, 13, 0, 0x43627530, false, true),
213                // SH
214                // Save the value 0x12348765 into address 0x43627530
215                Instruction::new(Opcode::SW, 29, 0, 0x43627530, false, true),
216                Instruction::new(Opcode::SH, 17, 0, 0x43627530, false, true),
217                Instruction::new(Opcode::LW, 12, 0, 0x43627530, false, true),
218                Instruction::new(Opcode::SH, 17, 0, 0x43627532, false, true),
219                Instruction::new(Opcode::LW, 11, 0, 0x43627530, false, true),
220                // 64-bit operations for RISCV64 testing
221                // Create a 64-bit value to test with
222                Instruction::new(Opcode::ADD, 10, 0, 0xFEDCBA9876543210, false, true),
223                // SD (Store Double/64-bit) and LD (Load Double/64-bit)
224                Instruction::new(Opcode::SD, 10, 0, 0x54321000, false, true),
225                Instruction::new(Opcode::LD, 9, 0, 0x54321000, false, true),
226                // LWU (Load Word Unsigned) - loads 32-bit value and zero-extends to 64-bit
227                Instruction::new(Opcode::LWU, 8, 0, 0x27654320, false, true),
228                // Test that LWU zero-extends (upper 32 bits should be 0)
229                Instruction::new(Opcode::LWU, 7, 0, 0x54321000, false, true), /* Load lower 32
230                                                                               * bits of our
231                                                                               * 64-bit value */
232            ];
233            add_halt(&mut instructions);
234            Program::new(instructions, 0, 0)
235        }
236    }
237}