stwo-cairo-adapter 1.2.2

Adapter for converting Cairo VM execution traces to Stwo prover format
Documentation
use std::collections::HashMap;
use std::ops::Deref;

use builtins::BuiltinSegments;
use cairo_vm::types::builtin_name::BuiltinName;
#[cfg(feature = "extract-mem-trace")]
use cairo_vm::vm::trace::trace_entry::RelocatedTraceEntry;
use memory::Memory;
use opcodes::StateTransitions;
use serde::{Deserialize, Serialize};

#[cfg(feature = "extract-mem-trace")]
use crate::memory::MemoryEntry;

pub mod adapter;
pub mod builtins;
pub mod decode;
pub mod memory;
pub mod opcodes;
pub mod relocator;
#[cfg(test)]
pub mod test_utils;

pub const N_REGISTERS: usize = 3;

/// Externally provided inputs for the Stwo prover.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ProverInput {
    pub state_transitions: StateTransitions,
    pub memory: Memory,
    pub pc_count: usize,
    pub public_memory_addresses: Vec<u32>,
    pub builtin_segments: BuiltinSegments,
    pub public_segment_context: PublicSegmentContext,
    #[cfg(feature = "extract-mem-trace")]
    pub relocated_mem: Vec<MemoryEntry>,
    #[cfg(feature = "extract-mem-trace")]
    pub relocated_trace: Vec<RelocatedTraceEntry>,
}

const N_PUBLIC_SEGMENTS: usize = 11;

/// Represents the pointer arguments of the `main` function.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PublicSegmentContext {
    present: [bool; N_PUBLIC_SEGMENTS],
}
impl PublicSegmentContext {
    pub fn new(vm_format: &[BuiltinName]) -> Self {
        let mut present = [false; N_PUBLIC_SEGMENTS];
        for builtin in vm_format {
            match builtin {
                BuiltinName::output => present[0] = true,
                BuiltinName::pedersen => present[1] = true,
                BuiltinName::range_check => present[2] = true,
                BuiltinName::ecdsa => present[3] = true,
                BuiltinName::bitwise => present[4] = true,
                BuiltinName::ec_op => present[5] = true,
                BuiltinName::keccak => present[6] = true,
                BuiltinName::poseidon => present[7] = true,
                BuiltinName::range_check96 => present[8] = true,
                BuiltinName::add_mod => present[9] = true,
                BuiltinName::mul_mod => present[10] = true,
                BuiltinName::segment_arena => {
                    // Do nothing.
                }
            }
        }
        Self { present }
    }

    pub const fn bootloader_context() -> Self {
        // Bootloader always uses every builtin.
        Self {
            present: [true; N_PUBLIC_SEGMENTS],
        }
    }
}
impl Deref for PublicSegmentContext {
    type Target = [bool; N_PUBLIC_SEGMENTS];

    fn deref(&self) -> &Self::Target {
        &self.present
    }
}

/// Sizes of memory address to ID and ID to value tables.
#[derive(Debug, Serialize, Deserialize)]
pub struct MemoryTablesSizes {
    /// Size of memory address to ID table.
    pub memory_address_to_id: usize,
    /// Size of memory ID to big value table.
    pub memory_id_to_big: usize,
    /// Size of memory ID to small value table.
    pub memory_id_to_small: usize,
}

/// Execution resources required to compute trace size.
#[derive(Debug, Serialize, Deserialize)]
pub struct ExecutionResources {
    /// Map opcode to the number of invocations.
    pub opcodes_instance_counter: HashMap<String, usize>,
    /// Map builtin to the number of invocations.
    pub builtin_instance_counter: HashMap<String, usize>,
    /// Sizes of memory tables.
    pub memory_tables_sizes: MemoryTablesSizes,
    /// Number of verify instructions, corresponds to the number of unique pc values.
    pub verify_instruction: usize,
}

impl ExecutionResources {
    /// Create execution resources from prover input.
    pub fn from_prover_input(input: &ProverInput) -> Self {
        ExecutionResources {
            opcodes_instance_counter: input
                .state_transitions
                .casm_states_by_opcode
                .counts()
                .into_iter()
                .collect(),
            builtin_instance_counter: input
                .builtin_segments
                .get_counts()
                .into_iter()
                .map(|(builtin, count)| (builtin.to_str_with_suffix().to_string(), count))
                .collect(),
            memory_tables_sizes: MemoryTablesSizes {
                memory_address_to_id: input.memory.address_to_id.len(),
                memory_id_to_big: input.memory.f252_values.len(),
                memory_id_to_small: input.memory.small_values.len(),
            },
            verify_instruction: input.pc_count,
        }
    }
}