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}