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