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