sp1_core_executor/
state.rs

1use std::{
2    collections::VecDeque,
3    fs::File,
4    io::{Seek, Write},
5};
6
7use hashbrown::HashMap;
8use serde::{Deserialize, Serialize};
9use sp1_stark::{baby_bear_poseidon2::BabyBearPoseidon2, StarkVerifyingKey};
10
11use crate::{
12    events::MemoryRecord,
13    memory::Memory,
14    record::{ExecutionRecord, MemoryAccessRecord},
15    syscalls::SyscallCode,
16    ExecutorMode, SP1ReduceProof,
17};
18
19/// Holds data describing the current state of a program's execution.
20#[derive(Debug, Clone, Default, Serialize, Deserialize)]
21#[repr(C)]
22pub struct ExecutionState {
23    /// The program counter.
24    pub pc: u32,
25
26    /// The shard clock keeps track of how many shards have been executed.
27    pub current_shard: u32,
28
29    /// The memory which instructions operate over. Values contain the memory value and last shard
30    /// + timestamp that each memory address was accessed.
31    pub memory: Memory<MemoryRecord>,
32
33    /// The global clock keeps track of how many instructions have been executed through all
34    /// shards.
35    pub global_clk: u64,
36
37    /// The clock increments by 4 (possibly more in syscalls) for each instruction that has been
38    /// executed in this shard.
39    pub clk: u32,
40
41    /// Uninitialized memory addresses that have a specific value they should be initialized with.
42    /// `SyscallHintRead` uses this to write hint data into uninitialized memory.
43    pub uninitialized_memory: Memory<u32>,
44
45    /// A stream of input values (global to the entire program).
46    pub input_stream: VecDeque<Vec<u8>>,
47
48    /// A stream of proofs (reduce vk, proof, verifying key) inputted to the program.
49    pub proof_stream:
50        Vec<(SP1ReduceProof<BabyBearPoseidon2>, StarkVerifyingKey<BabyBearPoseidon2>)>,
51
52    /// A ptr to the current position in the proof stream, incremented after verifying a proof.
53    pub proof_stream_ptr: usize,
54
55    /// A stream of public values from the program (global to entire program).
56    pub public_values_stream: Vec<u8>,
57
58    /// A ptr to the current position in the public values stream, incremented when reading from
59    /// `public_values_stream`.
60    pub public_values_stream_ptr: usize,
61
62    /// Keeps track of how many times a certain syscall has been called.
63    pub syscall_counts: HashMap<SyscallCode, u64>,
64}
65
66impl ExecutionState {
67    #[must_use]
68    /// Create a new [`ExecutionState`].
69    pub fn new(pc_start: u32) -> Self {
70        Self {
71            global_clk: 0,
72            // Start at shard 1 since shard 0 is reserved for memory initialization.
73            current_shard: 1,
74            clk: 0,
75            pc: pc_start,
76            memory: Memory::new_preallocated(),
77            uninitialized_memory: Memory::new_preallocated(),
78            input_stream: VecDeque::new(),
79            public_values_stream: Vec::new(),
80            public_values_stream_ptr: 0,
81            proof_stream: Vec::new(),
82            proof_stream_ptr: 0,
83            syscall_counts: HashMap::new(),
84        }
85    }
86}
87
88/// Holds data to track changes made to the runtime since a fork point.
89#[derive(Debug, Clone, Default)]
90#[allow(dead_code)]
91pub struct ForkState {
92    /// The `global_clk` value at the fork point.
93    pub global_clk: u64,
94    /// The original `clk` value at the fork point.
95    pub clk: u32,
96    /// The original `pc` value at the fork point.
97    pub pc: u32,
98    /// All memory changes since the fork point.
99    pub memory_diff: HashMap<u32, Option<MemoryRecord>>,
100    /// The original memory access record at the fork point.
101    pub op_record: MemoryAccessRecord,
102    /// The original execution record at the fork point.
103    pub record: ExecutionRecord,
104    /// Whether `emit_events` was enabled at the fork point.
105    pub executor_mode: ExecutorMode,
106    /// The cumulative number of unconstrained cycles during the entire execution.
107    pub total_unconstrained_cycles: u64,
108}
109
110impl ExecutionState {
111    /// Save the execution state to a file.
112    pub fn save(&self, file: &mut File) -> std::io::Result<()> {
113        let mut writer = std::io::BufWriter::new(file);
114        bincode::serialize_into(&mut writer, self).unwrap();
115        writer.flush()?;
116        writer.seek(std::io::SeekFrom::Start(0))?;
117        Ok(())
118    }
119}