Skip to main content

sp1_core_executor/
lib.rs

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