Skip to main content

sp1_core_machine/
executor.rs

1//! Execution utilities for tracing and generating execution records.
2
3use std::sync::Arc;
4
5use serde::{Deserialize, Serialize};
6use slop_algebra::PrimeField32;
7use sp1_core_executor::{events::MemoryRecord, ExecutionError, ExecutionRecord, SP1CoreOpts};
8use sp1_core_executor::{Program, TracingVMEnum};
9use sp1_hypercube::air::PROOF_NONCE_NUM_WORDS;
10use sp1_jit::MinimalTrace;
11use tracing::Level;
12
13/// The output of the machine executor.
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct ExecutionOutput {
16    pub public_value_stream: Vec<u8>,
17    pub cycles: u64,
18}
19
20/// Trace a single [`MinimalTrace`] (corresponding to a shard) and return the execution record.
21///
22/// This is the core tracing function that converts a minimal trace into a full execution record
23/// with all the events needed for proving.
24#[tracing::instrument(
25    level = Level::DEBUG,
26    name = "trace_chunk",
27    skip_all,
28)]
29pub fn trace_chunk<F: PrimeField32>(
30    program: Arc<Program>,
31    opts: SP1CoreOpts,
32    chunk: impl MinimalTrace,
33    proof_nonce: [u32; PROOF_NONCE_NUM_WORDS],
34    mut record: ExecutionRecord,
35) -> Result<(bool, ExecutionRecord, [MemoryRecord; 32]), ExecutionError> {
36    let mut vm = TracingVMEnum::new(&chunk, program, opts, proof_nonce, &mut record);
37    let status = vm.execute()?;
38    tracing::trace!("chunk ended at clk: {}", vm.clk());
39    tracing::trace!("chunk ended at pc: {}", vm.pc());
40
41    let pv = vm.public_values();
42
43    if status.is_shard_boundry() && (pv.commit_syscall == 1 || pv.commit_deferred_syscall == 1) {
44        tracing::trace!("commit syscall or commit deferred proofs across last two shards");
45
46        loop {
47            if vm.execute()?.is_done() {
48                let pv = *vm.public_values();
49
50                vm.record_mut().public_values.commit_syscall = 1;
51                vm.record_mut().public_values.commit_deferred_syscall = 1;
52                vm.record_mut().public_values.committed_value_digest = pv.committed_value_digest;
53                vm.record_mut().public_values.deferred_proofs_digest = pv.deferred_proofs_digest;
54
55                break;
56            }
57        }
58    }
59
60    vm.record_mut().finalize_public_values::<F>(true);
61
62    let registers = *vm.registers();
63    drop(vm);
64    Ok((status.is_done(), record, registers))
65}