Introduction

⚠️ Work in Progress Notice

This documentation is actively being developed and is subject to frequent changes. Some sections may be incomplete or pending review.

About Stoffel

Stoffel is a comprehensive framework for building privacy-preserving applications using secure Multi-Party Computation (MPC). It provides a complete toolchain that enables developers to create, compile, and deploy MPC applications without requiring deep cryptographic expertise.

The Stoffel Ecosystem

Stoffel consists of several integrated components that work together to provide a seamless development experience:

Core Components

  • Stoffel CLI: A comprehensive command-line interface for project management, compilation, development, and deployment
  • StoffelLang: A modern programming language with syntax inspired by Rust, Python, and JavaScript, designed specifically for MPC applications
  • StoffelVM: A register-based virtual machine optimized for multiparty computation with support for both clear and secret values
  • MPC Protocols: Rust implementation of secure multiparty computation protocols, including HoneyBadger MPC
  • Python SDK: High-level Python interface for integrating Stoffel into existing applications

Key Features

  • Modern Development Experience: Project templates, hot-reloading development server, and comprehensive CLI tools
  • Multiple Language Support: Templates and SDKs for Python, Rust, TypeScript, and Solidity integration
  • Rich Type System: Support for integers, floats, strings, booleans, arrays, objects, and closures
  • VM Architecture: Register-based design with separate clear/secret registers for efficient MPC operations
  • Production Ready: Built-in deployment tools with support for TEE and cloud environments

Current Status

The Stoffel ecosystem is under active development:

  • StoffelVM: Core virtual machine with instruction set and runtime (functional with quirks)
  • Stoffel CLI: Comprehensive project management and build tools
  • StoffelLang: Compiler with VM-compatible binary generation
  • Python SDK: Clean API with proper separation of concerns
  • 🚧 MPC Integration: Full MPC protocol integration (in progress)
  • 🚧 Production Deployment: TEE and cloud deployment features

Getting Started

The best way to start with Stoffel is to:

  1. Install the Stoffel CLI
  2. Create your first MPC project
  3. Explore the ecosystem

Documentation Structure

This documentation is organized to guide you through the Stoffel ecosystem:

What is Multi-Party Computation?

Multi-Party Computation (MPC) is a cryptographic technique that enables multiple parties to jointly compute a function over their inputs while keeping those inputs private. Think of it as a way for parties to collaborate on calculations without revealing their sensitive data to each other.

The Core Problem

Imagine three companies want to find out which one pays the highest average salary without revealing their actual salary data to competitors. Traditionally, they would need to:

  1. Trust a third party with their sensitive data, or
  2. Reveal their data to each other directly

Both options have serious privacy and competitive disadvantages. MPC provides a third option: compute the answer together without anyone learning anyone else's private data.

How MPC Works

The Basic Concept

MPC protocols work by:

  1. Secret Sharing: Each party's private input is split into multiple "shares" using cryptographic techniques
  2. Distributed Computation: The computation is performed on these shares across multiple nodes
  3. Result Reconstruction: The final result is reconstructed from the output shares

Throughout this process, no single party (including the computing nodes) ever sees the raw private data.

A Simple Example

Consider two parties, Alice and Bob, who want to compute (Alice's number + Bob's number) > 100 without revealing their numbers:

Alice has: 75 (secret)
Bob has: 30 (secret)

1. Secret Sharing:
   Alice's 75 → shares: [23, 17, 35]
   Bob's 30 → shares: [8, 12, 10]

2. Distributed Computation:
   Node 1: 23 + 8 = 31
   Node 2: 17 + 12 = 29
   Node 3: 35 + 10 = 45

   Each node computes: share > threshold_share

3. Result Reconstruction:
   Combine results → 105 > 100 = true

Neither Alice nor Bob learns the other's number, but they both learn that their sum exceeds 100.

Types of MPC

By Security Model

Semi-Honest (Honest-but-Curious)

  • Parties follow the protocol correctly but try to learn extra information
  • More efficient but assumes participants won't actively cheat
  • Suitable for many real-world scenarios where reputation matters

Malicious

  • Parties may deviate from the protocol arbitrarily
  • Stronger security guarantees but higher computational cost
  • Required when participants cannot be trusted to follow rules

By Network Assumptions

Honest Majority

  • Assumes more than half of participants are honest
  • Generally more efficient
  • Used by protocols like Stoffel's HoneyBadger MPC

Dishonest Majority

  • Works even if most participants are malicious
  • Higher computational and communication overhead
  • Typically used in two-party scenarios

Real-World Applications

Financial Services

Private Credit Scoring

Multiple banks → Collaborative credit risk assessment → Individual scores
(without sharing customer data)

Market Data Analysis

Trading firms → Joint market analysis → Insights
(without revealing trading strategies)

Healthcare

Medical Research

Hospitals → Disease pattern analysis → Research findings
(without sharing patient records)

Drug Discovery

Pharmaceutical companies → Compound effectiveness → New drugs
(without sharing proprietary research)

Government & Compliance

Tax Fraud Detection

Tax agencies → Cross-border fraud detection → Investigation leads
(without sharing taxpayer information)

Supply Chain Verification

Companies → Ethical sourcing verification → Compliance reports
(without revealing supplier details)

MPC vs Other Privacy Technologies

TechnologyPrivacy LevelPerformanceUse Cases
MPCHigh - inputs remain secretModerateMulti-party computation
Homomorphic EncryptionHigh - single party holds dataLowOutsourced computation
Differential PrivacyMedium - statistical privacyHighData analysis/sharing
Secure EnclavesHigh - hardware-basedHighTrusted execution

Challenges and Limitations

Performance Considerations

Computational Overhead

  • MPC operations are significantly slower than plain computation
  • Cryptographic operations add substantial cost
  • Trade-off between security and performance

Communication Complexity

  • Multiple rounds of communication between parties
  • Network latency affects overall computation time
  • Bandwidth requirements can be substantial

Practical Constraints

Setup Requirements

  • Coordinating multiple parties can be complex
  • Trust assumptions about protocol participants
  • Key management and secure channels

Programming Complexity

  • Traditional programming models don't directly apply
  • Need specialized tools and languages
  • Debugging and testing require new approaches

The Promise of MPC

Despite these challenges, MPC offers unprecedented opportunities:

Enabling New Business Models

Data Collaboration Without Exposure

  • Competitors can collaborate on common problems
  • Data monetization without data sharing
  • Cross-organizational analytics

Regulatory Compliance

  • GDPR-compliant data analysis
  • Financial privacy regulations
  • Healthcare data protection

Technical Advantages

Distributed Trust

  • No single point of failure
  • Reduced trust requirements
  • Cryptographic security guarantees

Selective Disclosure

  • Compute only what's needed
  • Reveal only specific results
  • Fine-grained privacy control

MPC in Practice

Modern MPC is becoming practical for real applications:

Performance Improvements

  • Specialized protocols for specific use cases
  • Hardware acceleration (GPUs, specialized chips)
  • Optimized implementations

Developer Tools

  • High-level programming languages
  • Automated optimization
  • Debugging and testing frameworks

Deployment Infrastructure

  • Cloud-based MPC services
  • Standardized protocols
  • Integration with existing systems

This is where Stoffel comes in - providing a complete framework that makes MPC accessible to developers without requiring deep cryptographic expertise.

Next Steps

To understand how Stoffel addresses these challenges and makes MPC practical for developers, see:

Why Stoffel?

While Multi-Party Computation offers powerful privacy-preserving capabilities, it has historically been challenging to implement and deploy in real-world applications. Stoffel addresses these challenges by providing a complete, developer-friendly framework that makes MPC accessible without requiring deep cryptographic expertise.

The MPC Development Challenge

Traditional Approach Problems

Cryptographic Complexity

Developer → Learn MPC protocols → Implement low-level cryptography → Debug → Deploy
(6-12 months of specialized learning)

Fragmented Ecosystem

  • Different protocols require different implementations
  • No standard development tools or workflows
  • Limited debugging and testing capabilities
  • Deployment requires extensive infrastructure knowledge

High Barrier to Entry

  • Requires PhD-level cryptography knowledge
  • Complex protocol implementation details
  • Performance optimization requires deep understanding
  • Integration with existing systems is difficult

Real-World Development Pain Points

Academic Research vs Production

Research Paper: "Our protocol is 10x faster!"
Reality: No compiler, no debugger, no deployment tools, no documentation

Tool Fragmentation

Protocol A: Custom C++ library
Protocol B: Research Python scripts
Protocol C: Academic proof-of-concept
Result: No interoperability, no standard practices

The Stoffel Solution

Stoffel provides a complete, integrated framework that transforms MPC development from a specialized research domain into a practical development experience.

🎯 Design Philosophy

Developer-First Approach

  • Familiar programming patterns and syntax
  • Comprehensive tooling and development environment
  • Clear separation between application logic and cryptographic complexity

Production-Ready

  • Battle-tested protocols and optimized implementations
  • Deployment tools for various environments
  • Monitoring, debugging, and performance optimization

Protocol Agnostic

  • Support for multiple MPC protocols
  • Easy switching between protocols based on requirements
  • Future-proof architecture for new protocol integration

Key Advantages

1. Familiar Development Experience

Modern Programming Language

// StoffelLang - familiar syntax, powerful MPC features
fn secure_auction(bids: secret [i32; 5]) -> secret i32 {
    let max_bid = secret(0);
    for bid in bids {
        if bid > max_bid {
            max_bid = bid;
        }
    }
    return max_bid;
}

Comprehensive CLI

# Just like other modern development tools
stoffel init secure-auction --template web3
stoffel dev --parties 5
stoffel build --release
stoffel deploy --target production

2. Complete Ecosystem

Integrated Components

StoffelLang → StoffelVM → MPC Protocols
    ↓             ↓            ↓
Compilation   Execution   Network Layer

Language SDK Integration

# Python developers can use MPC naturally
from stoffel import StoffelClient

result = await client.execute_with_inputs(
    secret_inputs={"salary": 75000, "performance": 8.5},
    public_inputs={"market_rate": 80000}
)

3. Protocol Flexibility

Multiple Protocol Support

  • HoneyBadger MPC: Current primary protocol
  • Future Protocols: Easy integration of new research
  • Hybrid Approaches: Mix protocols for optimal performance

Configuration-Driven

[mpc]
protocol = "honeybadger"
parties = 7
threshold = 2
field = "bls12-381"

4. Production-Ready Infrastructure

Development Tools

  • Hot-reloading development server
  • MPC simulation for local testing
  • Comprehensive debugging capabilities
  • Performance profiling and optimization

Deployment Options

  • Cloud deployment with auto-scaling
  • TEE (Trusted Execution Environment) integration
  • Kubernetes orchestration
  • Multi-region distributed deployment

Solving Real Problems

Problem 1: Expertise Barrier

Traditional Approach

Hire MPC expert → 6-month learning curve → Custom implementation → Maintenance burden
Cost: $500k+ per project, 18+ month timeline

Stoffel Approach

Learn StoffelLang → Build with familiar tools → Deploy with CLI
Cost: Weeks of development, existing team skills

Problem 2: Protocol Lock-in

Traditional Approach

Choose Protocol A → Build everything around it → Protocol B is better → Start over

Stoffel Approach

Write application logic once → Switch protocols via configuration → Optimize for use case

Problem 3: Integration Complexity

Traditional Approach

MPC Library → Custom networking → Database integration → API layer → Frontend
(Each component requires MPC expertise)

Stoffel Approach

Existing Application → Add Stoffel SDK → Configure privacy requirements → Deploy
(MPC complexity abstracted away)

Real-World Impact

Financial Services

Before Stoffel

Bank consortium wants privacy-preserving fraud detection
→ 18-month research project
→ Custom protocol implementation
→ Specialized infrastructure team
→ $2M+ investment, uncertain outcome

With Stoffel

stoffel init fraud-detection --template fintech
# Write business logic in familiar language
# Deploy to existing infrastructure
→ 3-month implementation, proven technology

Healthcare Research

Before Stoffel

Multi-hospital study requires:
→ Custom MPC implementation
→ HIPAA compliance engineering
→ Cross-institution coordination
→ Year-long technical negotiations

With Stoffel

# Standard MPC infrastructure
# Built-in compliance features
# Simple deployment across institutions
→ Focus on medical research, not cryptography

Web3 Applications

Before Stoffel

Private voting system:
→ Research MPC protocols
→ Implement custom solution
→ Handle key management
→ Deploy specialized infrastructure

With Stoffel

stoffel init private-voting --template web3-voting
# Standard patterns for blockchain integration
# Built-in key management
# Cloud deployment ready

Technical Advantages

Performance

Optimized Implementation

  • Register-based VM for efficient computation
  • Protocol-specific optimizations
  • Hardware acceleration support
  • Communication round minimization

Benchmarks vs Traditional Approaches

Setup Time:    Weeks vs Months
Development:   Days vs Months
Deployment:    Hours vs Weeks
Maintenance:   Minimal vs Ongoing

Security

Battle-Tested Protocols

  • Proven MPC protocol implementations
  • Formal security analysis
  • Regular security audits
  • Cryptographic best practices

Built-in Security Features

  • Automatic secret sharing
  • Secure communication channels
  • Access control and authentication
  • Audit logging and compliance

Scalability

Horizontal Scaling

  • Dynamic node addition/removal
  • Load balancing across computation nodes
  • Geographic distribution support
  • Auto-scaling based on demand

Vertical Optimization

  • Efficient memory usage
  • Parallel computation where possible
  • Optimized networking stack
  • Resource usage monitoring

Developer Benefits

Faster Time to Market

Traditional MPC: 12-18 months to production
Stoffel: 2-6 weeks to production

Lower Learning Curve

Traditional: PhD-level cryptography knowledge required
Stoffel: Standard programming skills sufficient

Reduced Risk

Traditional: Custom implementation, unknown bugs
Stoffel: Battle-tested framework, proven patterns

Better Integration

Traditional: Isolated MPC application
Stoffel: Seamless integration with existing systems

Future-Proof Architecture

Protocol Evolution

  • Easy integration of new MPC protocols
  • Backward compatibility with existing applications
  • Performance improvements without code changes
  • Research-to-production pipeline

Ecosystem Growth

  • Package manager for MPC libraries
  • Community templates and examples
  • Plugin system for specialized use cases
  • Integration with emerging privacy technologies

Getting Started Benefits

Day 1: Install Stoffel, create first MPC project Week 1: Deploy secure computation to cloud Month 1: Production-ready privacy-preserving application

Compare this to traditional MPC development where Month 1 is typically spent just understanding the underlying cryptography!

The Bottom Line

Stoffel transforms MPC from a research curiosity into a practical development tool. It's the difference between:

  • Building your own database vs using PostgreSQL
  • Implementing HTTP from scratch vs using a web framework
  • Writing custom cryptography vs using established libraries

Stoffel is the PostgreSQL of multi-party computation - a robust, production-ready foundation that lets you focus on your application instead of the underlying complexity.

Next Steps

Ready to experience the Stoffel difference?

Ecosystem Overview

The Stoffel ecosystem provides a complete toolchain for developing privacy-preserving applications using secure Multi-Party Computation (MPC). This page provides an overview of how the different components work together.

Component Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Stoffel CLI   │    │  StoffelLang    │    │   Python SDK    │
│                 │    │   Compiler      │    │                 │
│ Project Mgmt    │───▶│                 │    │ StoffelProgram  │
│ Build Tools     │    │ .stfl → .stfb   │    │ StoffelClient   │
│ Dev Server      │    │                 │    │                 │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         │                       ▼                       │
         │              ┌─────────────────┐              │
         │              │   StoffelVM     │              │
         │              │                 │              │
         └─────────────▶│ Register-based  │◀─────────────┘
                        │ Virtual Machine │
                        │ MPC Optimized   │
                        └─────────────────┘
                                 │
                                 ▼
                        ┌─────────────────┐
                        │ MPC Protocols   │
                        │                 │
                        │ HoneyBadger MPC │
                        │ Rust Implementation│
                        └─────────────────┘

Development Workflow

1. Project Initialization

Use the Stoffel CLI to create new projects with appropriate templates:

# Create a new MPC project with Python integration
stoffel init my-secure-app --template python

# Create a pure StoffelLang project
stoffel init privacy-lib --lib

2. Development

Write your privacy-preserving logic in StoffelLang and integrate with your preferred language:

StoffelLang Program (src/secure_add.stfl):

fn secure_add(a: secret i32, b: secret i32) -> secret i32 {
    return a + b;
}

fn main() {
    let result = secure_add(25, 17);
    reveal(result);
}

Python Integration:

from stoffel import StoffelProgram, StoffelClient

# Compile and execute
program = StoffelProgram("src/secure_add.stfl")
program.compile()

client = StoffelClient(config)
result = await client.execute_with_inputs(
    secret_inputs={"a": 25, "b": 17}
)

3. Development Server

Run the development server for hot reloading and MPC simulation:

stoffel dev --parties 5 --port 3000

4. Building and Deployment

Build optimized binaries for production:

# Create production build
stoffel build --release

# Deploy to TEE environment
stoffel deploy --target tee --env production

Component Details

Stoffel CLI

The central command-line interface that orchestrates the entire development workflow:

  • Project Management: Initialize projects with templates for different use cases
  • Compilation: Compile StoffelLang programs to VM bytecode
  • Development: Hot-reloading server with MPC simulation
  • Build System: Optimize and package applications for deployment
  • Deployment: Deploy to various targets including TEE and cloud environments

StoffelLang Compiler

A modern programming language designed specifically for MPC:

  • Syntax: Inspired by Rust, Python, and JavaScript for familiar development experience
  • Type System: Strong static typing with inference, supporting both clear and secret types
  • Compilation: Generates optimized bytecode compatible with StoffelVM
  • Integration: Works seamlessly with the CLI and other ecosystem components

StoffelVM

A register-based virtual machine optimized for multiparty computation:

  • Architecture: Separate clear and secret registers for efficient MPC operations
  • Instructions: Comprehensive instruction set for arithmetic, control flow, and memory operations
  • Types: Rich type system including primitives, objects, arrays, and closures
  • Runtime: Hook system for debugging and protocol integration

Python SDK

High-level Python interface for integrating Stoffel into existing applications:

  • StoffelProgram: Handles compilation, VM operations, and execution parameters
  • StoffelClient: Manages MPC network communication and data handling
  • API Design: Clean separation of concerns with explicit public/secret input handling
  • Integration: Easy integration into existing Python codebases

MPC Protocols

Rust implementation of secure multiparty computation protocols:

  • HoneyBadger MPC: Primary protocol implementation for secure computation
  • Cryptographic Fields: Support for multiple fields (BLS12-381, BN254, etc.)
  • Security: Configurable security parameters and threshold settings
  • Performance: Optimized for practical MPC applications

Integration Patterns

Standalone Applications

For new applications built entirely with Stoffel:

stoffel init secure-voting-app
cd secure-voting-app
stoffel dev

Library Integration

For adding privacy features to existing applications:

cd existing-project
stoffel init --lib --path ./privacy-module

Multiple Language Support

Templates available for different development environments:

  • Python: Full SDK integration with Poetry and pytest
  • Rust: FFI integration with StoffelVM
  • TypeScript: Node.js client integration
  • Solidity: Smart contract integration with MPC result verification

Security Model

The Stoffel ecosystem provides security through:

  • Type Safety: Clear distinction between public and secret data at the language level
  • Protocol Security: Proven MPC protocols with configurable security parameters
  • Deployment Security: TEE integration and secure deployment practices
  • Development Security: Simulation environment for testing without exposing real secrets

Next Steps

To start working with the Stoffel ecosystem:

  1. Install Stoffel - Set up the development environment
  2. Create Your First Project - Build a simple MPC application
  3. Learn StoffelLang - Master the programming language
  4. Explore the CLI - Understand all available commands and options
  5. Use the Python SDK - Integrate with Python applications

Installation

This guide will help you install Stoffel from source. Since Stoffel is currently in active development, you'll need to build the components manually from their Git repositories.

Prerequisites

System Requirements

Operating Systems

  • Linux (Ubuntu 20.04+, CentOS 8+, Arch Linux)
  • macOS (10.15+)
  • Windows (via WSL2 recommended)

Hardware Requirements

  • 4GB RAM minimum (8GB recommended for MPC development)
  • 2GB free disk space
  • Internet connection for downloading dependencies

Required Dependencies

Before installing Stoffel, make sure you have:

Essential Tools

  • Git (for cloning repositories)
  • Rust and Cargo (latest stable version)

Optional (based on your use case)

  • Python 3.8+ (for Python SDK integration)

Step-by-Step Installation

Step 1: Install Rust

If you don't have Rust installed:

# Install Rust and Cargo
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Source the environment
source ~/.cargo/env

# Verify installation
rustc --version
cargo --version

Step 2: Create a Stoffel Workspace

# Create a directory for all Stoffel components
mkdir ~/stoffel-dev
cd ~/stoffel-dev

Step 3: Clone the Repositories

Clone all the Stoffel components:

# Clone the main Stoffel CLI
git clone https://github.com/Stoffel-Labs/Stoffel.git

# Clone StoffelVM
git clone https://github.com/Stoffel-Labs/StoffelVM.git

# Clone Stoffel-Lang compiler
git clone https://github.com/Stoffel-Labs/Stoffel-Lang.git

# Clone MPC protocols
git clone https://github.com/Stoffel-Labs/mpc-protocols.git

# Clone Python SDK (optional)
git clone https://github.com/Stoffel-Labs/stoffel-python-sdk.git

Your directory structure should look like:

~/stoffel-dev/
├── Stoffel/                  # Main CLI
├── StoffelVM/               # Virtual Machine
├── Stoffel-Lang/            # Language compiler
├── mpc-protocols/           # MPC protocol implementations
└── stoffel-python-sdk/      # Python SDK (optional)

Step 4: Build the Components

Build each component in the correct order:

Build StoffelVM First

cd ~/stoffel-dev/StoffelVM

# Build the VM
cargo build --release

# Verify the build
./target/release/stoffel-run --version

Build Stoffel-Lang Compiler

cd ~/stoffel-dev/Stoffel-Lang

# Build the compiler
cargo build --release

# Verify the build
./target/release/stoffellang --version

Build MPC Protocols

cd ~/stoffel-dev/mpc-protocols

# Build the protocols
cargo build --release

Build the Main Stoffel CLI

cd ~/stoffel-dev/Stoffel

# Build the CLI
cargo build --release

# Verify the build
./target/release/stoffel --version

Step 5: Install to Your System

Add the built binaries to your PATH:

# Create a bin directory in your home folder
mkdir -p ~/.local/bin

# Copy the binaries
cp ~/stoffel-dev/Stoffel/target/release/stoffel ~/.local/bin/
cp ~/stoffel-dev/StoffelVM/target/release/stoffel-run ~/.local/bin/
cp ~/stoffel-dev/Stoffel-Lang/target/release/stoffellang ~/.local/bin/

# Add to your PATH (add this to your ~/.bashrc or ~/.zshrc)
export PATH="$HOME/.local/bin:$PATH"

# Reload your shell or source the profile
source ~/.bashrc  # or ~/.zshrc for zsh

Step 6: Verify Installation

Test that everything is working:

# Test Stoffel CLI
stoffel --version

# Test StoffelLang compiler
stoffellang --version

# Test StoffelVM
stoffel-run --version

# Test basic functionality
stoffel --help

Python SDK Installation (Optional)

If you want to use the Python SDK:

# Navigate to the Python SDK directory
cd ~/stoffel-dev/stoffel-python-sdk

# Install in development mode
pip install -e .

# Or create a virtual environment first (recommended)
python -m venv venv
source venv/bin/activate
pip install -e .

# Verify installation
python -c "import stoffel; print('Python SDK installed successfully')"

Development Setup

For development work, you can run the tools directly from their build directories:

# Create aliases for easier development (add to ~/.bashrc or ~/.zshrc)
alias stoffel-dev='~/stoffel-dev/Stoffel/target/release/stoffel'
alias stoffellang-dev='~/stoffel-dev/Stoffel-Lang/target/release/stoffellang'
alias stoffel-run-dev='~/stoffel-dev/StoffelVM/target/release/stoffel-run'

Keeping Up to Date

To update your Stoffel installation:

# Update each repository
cd ~/stoffel-dev/Stoffel && git pull && cargo build --release
cd ~/stoffel-dev/StoffelVM && git pull && cargo build --release
cd ~/stoffel-dev/Stoffel-Lang && git pull && cargo build --release
cd ~/stoffel-dev/mpc-protocols && git pull && cargo build --release

# Copy updated binaries
cp ~/stoffel-dev/Stoffel/target/release/stoffel ~/.local/bin/
cp ~/stoffel-dev/StoffelVM/target/release/stoffel-run ~/.local/bin/
cp ~/stoffel-dev/Stoffel-Lang/target/release/stoffellang ~/.local/bin/

Troubleshooting

Common Issues

Rust/Cargo not found

# Make sure Rust is properly installed
which cargo
cargo --version

# If not found, reinstall Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env

Build errors

# Make sure you have the latest Rust version
rustup update

# Clean and rebuild
cargo clean
cargo build --release

Command not found after installation

# Check if binaries are in the right place
ls -la ~/.local/bin/stoffel*

# Make sure PATH is set correctly
echo $PATH | grep -q "$HOME/.local/bin" && echo "PATH is correct" || echo "PATH needs updating"

# Add to PATH if needed
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Permission issues

# Make sure binaries are executable
chmod +x ~/.local/bin/stoffel*

Getting Help

If you encounter issues:

  1. Check the individual repository README files for component-specific instructions
  2. GitHub Issues: Report issues at the respective repository
  3. Build logs: Check cargo output for specific error messages

Next Steps

Now that you have Stoffel installed:

  1. Quick Start: Create your first project in 5 minutes
  2. Basic Usage: Learn the essential Stoffel commands
  3. Your First MPC Project: Build a complete privacy-preserving application

Development Workflow

For contributors or those wanting to modify Stoffel:

# Make changes to any component
cd ~/stoffel-dev/Stoffel
# ... make your changes ...

# Rebuild and reinstall
cargo build --release
cp target/release/stoffel ~/.local/bin/

# Test your changes
stoffel --version

This manual installation process gives you full control over the Stoffel components and allows you to track the latest development progress.

Quick Start

Get up and running with Stoffel in just a few minutes! This guide will walk you through creating your first privacy-preserving application using Multi-Party Computation.

Prerequisites

Make sure you have Stoffel installed on your system. If not, follow the Installation guide first.

# Verify Stoffel is installed
stoffel --version

5-Minute MPC Application

Let's create a simple secure addition application where two parties can compute the sum of their private numbers without revealing them to each other.

Step 1: Create a New Project

# Create a new Stoffel project
stoffel init secure-addition

# Navigate to the project directory
cd secure-addition

This creates a basic project structure:

secure-addition/
├── Stoffel.toml          # Project configuration
├── src/
│   └── main.stfl         # Main StoffelLang source file
├── tests/
└── README.md

Step 2: Write Your First StoffelLang Program

Open src/main.stfl and replace the contents with:

// Secure addition function
fn secure_add(a: secret i32, b: secret i32) -> secret i32 {
    return a + b;
}

// Main function - entry point for execution
fn main() {
    // These values would normally come from different parties
    let secret_value_a = secret(25);
    let secret_value_b = secret(17);

    // Perform secure computation
    let secure_result = secure_add(secret_value_a, secret_value_b);

    // Reveal the result (only the final result, not the inputs)
    let public_result = reveal(secure_result);

    // Print the result
    println("Secure addition result: {}", public_result);
}

Step 3: Compile Your Program

# Compile the StoffelLang program to VM bytecode
stoffel compile src/main.stfl --binary --output secure-addition.stfbin

This will:

  • Parse and compile your StoffelLang code
  • Generate optimized VM bytecode
  • Create a compiled .stfbin file ready for execution

You should see output like:

Compiling src/main.stfl...
Compilation successful!
Generating VM-compatible binary...
Binary saved to secure-addition.stfbin

Step 4: Run Your Application

# Execute the compiled program using StoffelVM
stoffel-run secure-addition.stfbin main

This runs your secure computation and you should see:

Program returned: Unit

The program executes successfully! For more detailed execution tracing, you can use debug flags:

# Trace instruction execution
stoffel-run secure-addition.stfbin main --trace-instr

# Trace register operations
stoffel-run secure-addition.stfbin main --trace-regs

# Trace function calls and stack operations
stoffel-run secure-addition.stfbin main --trace-stack

Step 5: Development Workflow

Note: The integrated stoffel run command is currently under development. For now, use this workflow:

# 1. Edit your .stfl file
# 2. Recompile when you make changes
stoffel compile src/main.stfl --binary --output secure-addition.stfbin

# 3. Test the changes
stoffel-run secure-addition.stfbin main

# 4. For debugging, enable tracing
stoffel-run secure-addition.stfbin main --trace-instr --trace-regs

Understanding What Happened

The Magic of MPC

In your secure addition example:

  1. Secret Sharing: Your inputs (25 and 17) were automatically split into shares
  2. Distributed Computation: Each party computed on shares without seeing the original values
  3. Result Reconstruction: The final result (42) was reconstructed from the output shares
Party 1: Receives shares [8, 23] → Computes 8 + 23 = 31
Party 2: Receives shares [5, 12] → Computes 5 + 12 = 17
Party 3: Receives shares [12, -18] → Computes 12 + (-18) = -6
...
Result: Reconstruct 31 + 17 + (-6) + ... = 42

No single party ever saw your original values (25 and 17)!

StoffelLang Features

Your simple program demonstrated several key features:

  • Secret Types: secret i32 for private data
  • Automatic Operations: + works on secret values
  • Reveal Operations: reveal() to make results public
  • Built-in Functions: println() for output

Next Steps

Try Different Examples

Experiment with different StoffelLang programs by modifying src/main.stfl:

# After editing, recompile and run
stoffel compile src/main.stfl --binary --output example.stfbin
stoffel-run example.stfbin main

Future Features

Coming Soon: The following features are currently under development:

  • Templates: stoffel init --template <name> for common use cases
  • Python SDK Integration: Seamless Python bindings
  • Development Server: stoffel dev with hot reloading and web interface
  • Advanced CLI: Testing, deployment, and protocol management commands

Common Commands

Here are the essential commands you'll use regularly:

# Project creation
stoffel init <name>                 # Create new project structure

# Compilation
stoffel compile <source.stfl>       # Compile to bytecode
stoffel compile <source.stfl> --binary --output <file.stfbin>

# Compilation options
--binary            # Generate VM-compatible binary format
--output/-o         # Specify output file path
--print-ir          # Show intermediate representations
-O0 to -O3          # Optimization levels (0=none, 3=maximum)
--disassemble       # Disassemble compiled binary

# Execution (using StoffelVM)
stoffel-run <program.stfbin> [entry_function] [flags]

# Execution debugging flags:
--trace-instr       # Trace instructions before/after execution
--trace-regs        # Trace register reads/writes
--trace-stack       # Trace function calls and stack operations

# Help and information
stoffel --help                      # Show CLI help
stoffel compile --help              # Show compiler help
stoffel-run --help                  # Show VM runner help

Development Note: Advanced CLI features like stoffel run, stoffel dev, stoffel test, and stoffel deploy are currently under development. The core workflow using stoffel compile and stoffel-run is fully functional.

What's Next?

Now that you've created your first MPC application:

  1. Basic Usage: Learn all the essential Stoffel CLI commands
  2. Your First MPC Project: Build a more complex privacy-preserving application
  3. StoffelLang Overview: Deep dive into the programming language
  4. Python SDK: Integrate Stoffel with Python applications

Troubleshooting

Compilation Errors

# Check detailed compiler output
stoffel compile src/main.stfl --print-ir --binary --output debug.stfbin

# The --print-ir flag shows intermediate representations including:
# - Generated bytecode
# - Constants and labels
# - Function chunks

Runtime Errors

# Use tracing flags to debug execution
stoffel-run program.stfbin main --trace-instr --trace-regs --trace-stack

# This provides detailed execution traces showing:
# - Instruction execution order
# - Register read/write operations
# - Function call stack operations

Common Issues

"Error loading binary": Ensure the .stfbin file was compiled successfully and the path is correct.

"Execution error": Check that the entry function exists and has the correct signature using --trace-instr for debugging.

Example Variations

Try these variations of the secure addition example:

Secure Comparison

fn secure_compare(a: secret i32, b: secret i32) -> secret bool {
    return a > b;
}

fn main() {
    let alice_value = secret(75);
    let bob_value = secret(68);

    let alice_wins = secure_compare(alice_value, bob_value);
    let result = reveal(alice_wins);

    println("Alice has higher value: {}", result);
}

Secure Average

fn secure_average(values: secret [i32; 3]) -> secret i32 {
    let sum = secret(0);
    for value in values {
        sum = sum + value;
    }
    return sum / secret(3);
}

fn main() {
    let party_values = secret([85, 92, 78]);
    let average = secure_average(party_values);
    let result = reveal(average);

    println("Average score: {}", result);
}

You're now ready to build privacy-preserving applications with Stoffel! The framework handles all the complex cryptography while you focus on your application logic.

Basic Usage

This guide covers the essential Stoffel CLI commands and workflows you'll use in your daily development. After completing the Quick Start, you should be familiar with basic project creation and development.

Core Workflow

The typical Stoffel development workflow follows this pattern:

stoffel init → edit code → stoffel compile → stoffel-run → repeat

Note: Advanced workflow commands like stoffel dev, stoffel test, stoffel build, and stoffel deploy are under development.

Let's explore each command in detail.

Project Management

Creating Projects

# Basic project creation
stoffel init my-project

# Using templates
stoffel init py-app --template python
stoffel init rust-app --template rust
stoffel init web-app --template typescript

# Library projects
stoffel init crypto-utils --lib

# Interactive setup
stoffel init --interactive

Template Options

# List all available templates
stoffel templates list

# Get template details
stoffel templates show python

# Create template with specific options
stoffel init solidity-app --template solidity

Project Structure

A typical Stoffel project looks like:

my-project/
├── Stoffel.toml              # Project configuration
├── src/                      # StoffelLang source files
│   ├── main.stfl            # Main program
│   ├── lib.stfl             # Library functions
│   └── utils/               # Module organization
│       └── crypto.stfl
├── tests/                   # Test files
│   ├── unit.stfl           # Unit tests
│   └── integration.stfl     # Integration tests
├── build/                   # Compiled outputs (generated)
├── .stoffel/               # Local configuration (gitignored)
└── README.md

Configuration

The Stoffel.toml file controls project settings:

[package]
name = "my-project"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2024"

[mpc]
protocol = "honeybadger"
parties = 5
threshold = 1
field = "bls12-381"

[build]
optimization_level = 2
target = "vm"
output_dir = "build"

[dev]
hot_reload = true
simulation_mode = true
port = 8080
log_level = "info"

[dependencies]
# Future: MPC libraries will be listed here

[dev-dependencies]
# Development-only dependencies

Development Commands

Compilation

# Compile all source files in src/
stoffel compile

# Compile specific file
stoffel compile src/main.stfl

# Compile with different optimization levels
stoffel compile -O0  # No optimization (fastest compile)
stoffel compile -O1  # Basic optimization
stoffel compile -O2  # Standard optimization (default)
stoffel compile -O3  # Maximum optimization (slower compile)

# Generate VM-compatible binaries
stoffel compile --binary
stoffel compile src/main.stfl --binary --output program.stfb

# Show intermediate representations during compilation
stoffel compile --print-ir

# Disassemble compiled binaries
stoffel compile compiled.stfb --disassemble

Compilation Outputs

# After compilation, you'll find:
main.stfbin                    # VM-compatible binary (when using --binary)

Execution

# Execute compiled programs (use .bin files for VM execution)
stoffel-run program.stfbin main

# Execute with command line arguments
stoffel-run program.stfbin main arg1 arg2

# Debug execution with tracing
stoffel-run program.stfbin main --trace-instr    # Trace instructions
stoffel-run program.stfbin main --trace-regs     # Trace register operations
stoffel-run program.stfbin main --trace-stack    # Trace function calls

# Combined debugging
stoffel-run program.stfbin main --trace-instr --trace-regs --trace-stack

Development Workflow

For iterative development, use this pattern:

# 1. Edit your StoffelLang source files

# 2. Compile your changes
stoffel compile src/main.stfl --binary --output program.stfbin

# 3. Test execution
stoffel-run program.stfbin main

# 4. Debug if needed
stoffel-run program.stfbin main --trace-instr

# 5. Repeat

Coming Soon: The integrated development server (stoffel dev) with hot reloading, web interface, and MPC simulation is under development.

Testing

Coming Soon: The integrated testing framework (stoffel test) is under development.

For now, test your programs manually:

# Create test programs in tests/ directory
# Compile and run them individually
stoffel compile tests/test_addition.stfl --binary --output test_addition.stfbin
stoffel-run test_addition.stfbin main

# Use tracing to verify behavior
stoffel-run test_addition.stfbin main --trace-instr --trace-regs

Building and Deployment

Building Projects

Coming Soon: The integrated build system (stoffel build) and deployment tools (stoffel deploy) are under development.

For now, use the compilation workflow:

# Build for production (with maximum optimization)
stoffel compile src/main.stfl --binary --output production.stfbin -O3

# Verify the build
stoffel-run production.stfbin main

# Disassemble to inspect the compiled output
stoffel compile production.stfbin --disassemble

Utility Commands

Information and Help

# Show CLI help
stoffel --help

# Show compilation help
stoffel compile --help

# Show version information
stoffel --version

# Show help for specific flags
stoffel help compile -O      # Optimization levels
stoffel help compile --binary # Binary output format

Template Management

Coming Soon: Most advanced CLI features are under development.

Available template operations:

# List available templates
stoffel templates list

# Show template details
stoffel templates show python

Advanced Usage

Multi-File Projects

For projects with multiple StoffelLang files:

# Compile all files in src/ directory
stoffel compile

# This compiles all .stfl files found in src/
# Each file is compiled independently

Optimization Levels

# Development: Fast compilation, no optimization
stoffel compile -O0

# Balanced: Some optimization, reasonable compile time
stoffel compile -O2

# Production: Maximum optimization, slower compilation
stoffel compile -O3 --binary --output optimized.stfbin

Debugging and Analysis

# View intermediate representations
stoffel compile src/main.stfl --print-ir

# Disassemble compiled bytecode
stoffel compile program.stfbin --disassemble

# Runtime debugging with comprehensive tracing
stoffel-run program.stfbin main --trace-instr --trace-regs --trace-stack

Common Workflows

Daily Development

# 1. Edit your StoffelLang files in src/
# 2. Compile frequently during development
stoffel compile src/main.stfl --binary --output program.stfbin

# 3. Test your changes
stoffel-run program.stfbin main

# 4. Debug when needed
stoffel-run program.stfbin main --trace-instr

# 5. Version control
git add . && git commit -m "Update MPC logic"

Debugging Issues

# Compilation problems
stoffel compile src/main.stfl --print-ir    # Show compilation details

# Runtime issues
stoffel-run program.stfbin main --trace-instr --trace-regs --trace-stack

# Understanding bytecode
stoffel compile program.stfbin --disassemble

Production Preparation

# Create optimized build
stoffel compile src/main.stfl --binary --output production.stfbin -O3

# Verify it works
stoffel-run production.stfbin main

# Inspect the optimized bytecode
stoffel compile production.stfbin --disassemble

Shell Integration

Useful Aliases

Add to your shell profile (.bashrc, .zshrc, etc.):

# Common aliases
alias sc='stoffel compile'
alias sr='stoffel-run'
alias si='stoffel init'

# Useful functions
function stoffel-new() {
    stoffel init "$1" --template "${2:-python}"
    cd "$1"
}

function stoffel-compile-run() {
    stoffel compile "$1" --binary --output "${1%.stfl}.stfbin" && \
    stoffel-run "${1%.stfl}.stfbin" main
}

Next Steps

Now that you understand basic Stoffel usage:

  1. Your First MPC Project: Build a complete real-world application
  2. CLI Overview: Detailed CLI reference and advanced features
  3. StoffelLang Overview: Learn the programming language in depth
  4. Architecture Overview: Understand how Stoffel works internally

Troubleshooting

Common Issues

Compilation Failures

# Check syntax and get detailed error output
stoffel compile src/main.stfl --print-ir

# Verify file paths and structure
ls src/  # Make sure .stfl files exist

# Try compiling individual files to isolate issues
stoffel compile src/main.stfl --binary --output test.stfbin

Runtime Errors

# Use comprehensive tracing to debug
stoffel-run program.stfbin main --trace-instr --trace-regs --trace-stack

# Check that the binary was created correctly
ls -la *.stfbin

# Verify entry function exists
stoffel compile program.stfbin --disassemble | grep -i main

Performance Issues

# Use minimal optimization during development
stoffel compile src/main.stfl -O0 --binary --output debug.stfbin

# For production, use maximum optimization
stoffel compile src/main.stfl -O3 --binary --output production.stfbin

Path Issues

# Make sure you're in the project directory
pwd
ls  # Should see Stoffel.toml and src/ directory

# Check available help
stoffel --help
stoffel compile --help

Your First MPC Project

Now that you're familiar with Stoffel basics, let's build a complete real-world privacy-preserving application. We'll create a secure salary benchmarking system where multiple companies can collaboratively determine market salary ranges without revealing their individual employee data.

Project Overview

The Problem

Companies want to understand competitive salary ranges for different roles, but:

  • They can't share sensitive employee salary data directly
  • Third-party salary surveys are expensive and often outdated
  • Traditional benchmarking requires trusting a central party with sensitive data

The MPC Solution

Using Stoffel, companies can:

  • Compute accurate salary statistics collaboratively
  • Keep individual employee salaries completely private
  • Get real-time market insights without data exposure
  • Maintain compliance with privacy regulations

What We'll Build

A system that allows companies to:

  1. Submit encrypted salary data for specific roles
  2. Compute statistics (average, median, percentiles) across all companies
  3. Receive market insights without seeing other companies' data
  4. Generate compliance reports showing no data was exposed

Project Setup

Step 1: Initialize the Project

# Create the project with default template
stoffel init salary-benchmark

# Navigate to the project
cd salary-benchmark

# Examine the generated structure
tree

You'll see a structure like:

salary-benchmark/
├── Stoffel.toml              # Project configuration
├── src/
│   ├── main.stfl            # Main computation logic
│   ├── types.stfl           # Data type definitions
│   └── stats.stfl           # Statistical functions
├── integrations/
│   ├── python/              # Python SDK integration
│   │   ├── client.py
│   │   └── requirements.txt
│   └── web/                 # Web interface
│       ├── index.html
│       └── app.js
├── tests/
│   ├── unit.stfl
│   └── integration.stfl
├── deployment/
│   └── production.toml
└── README.md

Step 2: Configure the Project

Edit Stoffel.toml to customize for our use case:

[package]
name = "salary-benchmark"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2024"
description = "Privacy-preserving salary benchmarking system"

[mpc]
protocol = "honeybadger"
parties = 5  # Minimum 5 companies for statistical significance
threshold = 1  # Up to 1 corrupted party
field = "bls12-381"

[build]
optimization_level = 2
target = "vm"

[dev]
hot_reload = true
port = 8080
parties = 5

[deployment.production]
type = "cloud"
provider = "aws"
region = "us-west-2"
parties = 10  # More parties in production
auto_scaling = true

Building the Core Logic

Step 3: Define Data Types

Create src/types.stfl:

# Data types for salary benchmarking

# Represents a salary entry from a company
type SalaryData = object
  role_id: int64           # Standardized role identifier
  experience_level: int64  # Years of experience (0-4: junior, 5-9: mid, 10+: senior)
  salary: secret int64     # Annual salary in dollars (secret!)
  location_tier: int64     # Cost of living tier (1: high, 2: medium, 3: low)
  company_size: int64      # 1: startup, 2: mid-size, 3: enterprise

# Statistics we want to compute
type SalaryStats = object
  role_id: int64
  experience_level: int64
  location_tier: int64
  count: int64                    # Number of data points (public)
  min_salary: secret int64        # Minimum salary (secret until revealed)
  max_salary: secret int64        # Maximum salary
  avg_salary: secret int64        # Average salary
  median_salary: secret int64     # Median salary
  percentile_25: secret int64     # 25th percentile
  percentile_75: secret int64     # 75th percentile

# Results that can be safely revealed
type PublicStats = object
  role_id: int64
  experience_level: int64
  location_tier: int64
  count: int64
  avg_salary: int64        # Now public
  median_salary: int64
  percentile_25: int64
  percentile_75: int64
  salary_range_min: int64  # Minimum for range (not exact min)
  salary_range_max: int64  # Maximum for range (not exact max)

Step 4: Implement Statistical Functions

Create src/stats.stfl:

# Simple statistical functions for salary benchmarking

# Calculate comprehensive salary statistics
proc calculate_salary_stats(
    salary_data: SalaryData,
    role_filter: int64,
    experience_filter: int64,
    location_filter: int64
): SalaryStats =
  # Filter data for the specific role/experience/location
  let filtered_salaries: secret int64 = salary_data.salary
  let count: int64 = 1

  # In a real implementation, this would process multiple entries
  # For now, simplified to show the concept

  # Calculate basic statistics
  let sum = filtered_salaries
  let avg = sum  # Single data point case

  return SalaryStats(
    role_id: role_filter,
    experience_level: experience_filter,
    location_tier: location_filter,
    count: count,
    min_salary: filtered_salaries,
    max_salary: filtered_salaries,
    avg_salary: avg,
    median_salary: filtered_salaries,
    percentile_25: filtered_salaries,
    percentile_75: filtered_salaries
  )

# Safely reveal statistics (with privacy protection)
proc reveal_safe_stats(stats: SalaryStats): PublicStats =
  # Only reveal if we have enough data points for statistical significance
  if stats.count < 5:
    return PublicStats(
      role_id: stats.role_id,
      experience_level: stats.experience_level,
      location_tier: stats.location_tier,
      count: stats.count,
      avg_salary: 0,
      median_salary: 0,
      percentile_25: 0,
      percentile_75: 0,
      salary_range_min: 0,
      salary_range_max: 0
    )

  # For demo purposes, we'll use a simplified reveal
  # In practice, this would use proper MPC reveal operations
  print("Revealing salary statistics...")
  return PublicStats(
    role_id: stats.role_id,
    experience_level: stats.experience_level,
    location_tier: stats.location_tier,
    count: stats.count,
    avg_salary: 95000,  # Demo value
    median_salary: 92000,
    percentile_25: 85000,
    percentile_75: 105000,
    salary_range_min: 85000,
    salary_range_max: 105000
  )

Step 5: Main Application Logic

Edit src/main.stfl:

# Main entry point for salary benchmarking
proc main() =
  print("🔒 Starting Secure Salary Benchmarking System")
  print("📊 Collecting data from participating companies...")

  # In a real system, this data would come from multiple companies
  # Each company would submit their data separately
  let company_data = load_salary_data()

  # Common roles we want to benchmark
  let role_software_engineer: int64 = 1
  let role_data_scientist: int64 = 2
  let role_product_manager: int64 = 3
  let role_designer: int64 = 4

  # Experience levels
  let junior: int64 = 1    # 0-4 years
  let mid: int64 = 2       # 5-9 years
  let senior: int64 = 3    # 10+ years

  # Location tiers
  let high_cost: int64 = 1 # SF, NYC, etc.
  let mid_cost: int64 = 2  # Austin, Seattle, etc.
  let low_cost: int64 = 3  # Remote, smaller cities

  print("🧮 Computing secure statistics...")

  # Generate a simple salary report
  generate_salary_report(company_data, role_software_engineer, "Software Engineer")

  print("✅ Benchmarking complete! No individual data was exposed.")

# Generate a simple salary report for a specific role
proc generate_salary_report(data: SalaryData, role_id: int64, role_name: string) =
  print("📈 Analyzing " + role_name + " positions...")

  let stats = calculate_salary_stats(data, role_id, mid, high_cost)
  let public_stats = reveal_safe_stats(stats)

  # Print results
  print("   Mid-Level High-Cost (" + $public_stats.count + " data points):")
  print("     Average: $" + $public_stats.avg_salary)
  print("     Median: $" + $public_stats.median_salary)
  print("     Range: $" + $public_stats.salary_range_min + " - $" + $public_stats.salary_range_max)

# Load salary data (in reality, this comes from multiple companies)
proc load_salary_data(): SalaryData =
  # This would be replaced with actual data submission from companies
  # For demo purposes, we'll create some sample data

  return SalaryData(
    role_id: 1,
    experience_level: 2,
    salary: secret(95000),
    location_tier: 1,
    company_size: 2
  )

Testing the Application

Step 6: Write Comprehensive Tests

Create tests/unit.stfl:

# Simple test for salary statistics

# Note: Testing framework syntax is simplified for demonstration
# In practice, StoffelLang would have a proper testing framework

proc test_salary_calculation() =
  print("Testing salary statistics calculation...")

  # Create test data
  let test_data = SalaryData(
    role_id: 1,
    experience_level: 2,
    salary: secret(95000),
    location_tier: 1,
    company_size: 2
  )

  let stats = calculate_salary_stats(test_data, 1, 2, 1)
  let public_stats = reveal_safe_stats(stats)

  # Verify basic functionality
  if public_stats.count == 1:
    print("✅ Test passed: Basic calculation works")
  else:
    print("❌ Test failed: Incorrect count")

proc test_insufficient_data_protection() =
  print("Testing privacy protection...")

  let test_data = SalaryData(
    role_id: 1,
    experience_level: 2,
    salary: secret(100000),
    location_tier: 1,
    company_size: 2
  )

  let stats = calculate_salary_stats(test_data, 1, 2, 1)
  let public_stats = reveal_safe_stats(stats)

  # Should not reveal statistics for insufficient data
  if public_stats.count < 5:
    print("✅ Test passed: Privacy protection works")
  else:
    print("❌ Test failed: Privacy protection failed")

proc main() =
  test_salary_calculation()
  test_insufficient_data_protection()
  print("All tests completed")

Step 7: Run Tests

# Compile and run the test file
stoffel compile tests/unit.stfl --binary --output unit_tests.stfbin
stoffel-run unit_tests.stfbin main

# Run the main application
stoffel compile src/main.stfl --binary --output salary_benchmark.stfbin
stoffel-run salary_benchmark.stfbin main

# With debugging to see execution details
stoffel-run salary_benchmark.stfbin main --trace-instr

Note: The integrated stoffel test command is under development. For now, compile and run test files manually.

Adding Python Integration

Step 8: Company Client Implementation

Edit integrations/python/client.py:

import asyncio
import json
from typing import Dict, List, Optional
from stoffel import StoffelProgram, StoffelClient

class SalaryBenchmarkClient:
    """Client for companies to participate in salary benchmarking"""

    def __init__(self, config: Dict):
        self.company_id = config["company_id"]
        self.mpc_nodes = config["mpc_nodes"]
        self.program = StoffelProgram("src/main.stfl")
        self.client = None

    async def connect(self):
        """Connect to the MPC network"""
        self.program.compile()

        self.client = StoffelClient({
            "nodes": self.mpc_nodes,
            "client_id": self.company_id,
            "program_id": "salary_benchmark"
        })

        await self.client.connect()
        print(f"✅ Company {self.company_id} connected to MPC network")

    async def submit_salary_data(self, employee_data: List[Dict]) -> str:
        """Submit company salary data for benchmarking"""

        # Convert employee data to the format expected by StoffelLang
        formatted_data = []
        for employee in employee_data:
            formatted_data.append({
                "role_id": employee["role_id"],
                "experience_level": self._map_experience(employee["years_experience"]),
                "salary": employee["annual_salary"],  # This becomes secret!
                "location_tier": employee["location_tier"],
                "company_size": employee.get("company_size", 2)
            })

        # Submit as secret inputs
        result = await self.client.execute_with_inputs(
            secret_inputs={"salary_data": formatted_data},
            public_inputs={"company_id": self.company_id}
        )

        print(f"📊 Submitted {len(employee_data)} salary records")
        return result

    async def get_benchmark_results(self, role_id: int, experience_level: int,
                                  location_tier: int) -> Optional[Dict]:
        """Get salary benchmark results for specific criteria"""

        result = await self.client.execute_with_inputs(
            public_inputs={
                "query_type": "get_stats",
                "role_id": role_id,
                "experience_level": experience_level,
                "location_tier": location_tier
            }
        )

        return result

    def _map_experience(self, years: int) -> int:
        """Map years of experience to experience level"""
        if years < 5:
            return 1  # Junior
        elif years < 10:
            return 2  # Mid-level
        else:
            return 3  # Senior

    async def disconnect(self):
        """Disconnect from MPC network"""
        if self.client:
            await self.client.disconnect()

# Example usage
async def main():
    # Configuration for a participating company
    config = {
        "company_id": "tech_company_1",
        "mpc_nodes": [
            "http://mpc-node1:9000",
            "http://mpc-node2:9000",
            "http://mpc-node3:9000",
            "http://mpc-node4:9000",
            "http://mpc-node5:9000"
        ]
    }

    client = SalaryBenchmarkClient(config)
    await client.connect()

    # Example: Submit company salary data
    company_salaries = [
        {
            "role_id": 1,  # Software Engineer
            "years_experience": 6,
            "annual_salary": 95000,
            "location_tier": 1  # High-cost area
        },
        {
            "role_id": 1,  # Software Engineer
            "years_experience": 8,
            "annual_salary": 110000,
            "location_tier": 1
        },
        {
            "role_id": 2,  # Data Scientist
            "years_experience": 5,
            "annual_salary": 105000,
            "location_tier": 1
        }
        # Company would submit all their relevant salary data
    ]

    # Submit data (salaries remain secret!)
    await client.submit_salary_data(company_salaries)

    # Query benchmark results
    results = await client.get_benchmark_results(
        role_id=1,           # Software Engineer
        experience_level=2,  # Mid-level
        location_tier=1      # High-cost area
    )

    print("📈 Market Benchmark Results:")
    print(f"   Average Salary: ${results['avg_salary']:,}")
    print(f"   Median Salary: ${results['median_salary']:,}")
    print(f"   Salary Range: ${results['salary_range_min']:,} - ${results['salary_range_max']:,}")
    print(f"   Based on {results['count']} data points")

    await client.disconnect()

if __name__ == "__main__":
    asyncio.run(main())

Development and Testing

Step 9: Run the Development Environment

# Start development server
stoffel dev --parties 5

# In another terminal, test the Python integration
cd integrations/python
pip install -r requirements.txt
python client.py

You should see:

🔒 Starting Secure Salary Benchmarking System
📊 Collecting data from participating companies...
🧮 Computing secure statistics...
📈 Analyzing Software Engineer positions...
   Mid-Level High-Cost (10 data points):
     Average: $98,500
     Median: $97,000
     Range: $85,000 - $115,000
     25th-75th percentile: $90,000 - $105,000
✅ Benchmarking complete! No individual data was exposed.

Step 10: Add Web Interface

Create integrations/web/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Salary Benchmark Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
        .card { border: 1px solid #ddd; padding: 20px; border-radius: 8px; }
        .secure-indicator { color: green; font-weight: bold; }
        .stats { font-size: 18px; margin: 10px 0; }
    </style>
</head>
<body>
    <h1>🔒 Secure Salary Benchmarking Dashboard</h1>
    <p class="secure-indicator">🛡️ All individual salary data remains private and encrypted</p>

    <div class="dashboard">
        <div class="card">
            <h3>Software Engineer - Mid-Level (High-Cost Areas)</h3>
            <div class="stats">
                <div>📊 Data Points: <span id="se-count">Loading...</span></div>
                <div>💰 Average: $<span id="se-avg">Loading...</span></div>
                <div>📈 Median: $<span id="se-median">Loading...</span></div>
                <div>📉 Range: $<span id="se-min">Loading...</span> - $<span id="se-max">Loading...</span></div>
            </div>
            <canvas id="se-chart" width="400" height="200"></canvas>
        </div>

        <div class="card">
            <h3>Data Scientist - Mid-Level (High-Cost Areas)</h3>
            <div class="stats">
                <div>📊 Data Points: <span id="ds-count">Loading...</span></div>
                <div>💰 Average: $<span id="ds-avg">Loading...</span></div>
                <div>📈 Median: $<span id="ds-median">Loading...</span></div>
                <div>📉 Range: $<span id="ds-min">Loading...</span> - $<span id="ds-max">Loading...</span></div>
            </div>
            <canvas id="ds-chart" width="400" height="200"></canvas>
        </div>
    </div>

    <div class="card" style="margin-top: 20px;">
        <h3>🔐 Privacy Guarantees</h3>
        <ul>
            <li>✅ Individual salaries are never revealed to any party</li>
            <li>✅ Computations use secure multi-party computation (MPC)</li>
            <li>✅ Statistics only shown when ≥5 data points (for privacy)</li>
            <li>✅ All communication is encrypted and authenticated</li>
            <li>✅ No central party can see raw salary data</li>
        </ul>
    </div>

    <script>
        // Fetch and display salary benchmark data
        async function loadBenchmarkData() {
            try {
                const response = await fetch('http://localhost:8080/api/benchmark');
                const data = await response.json();

                updateStats('se', data.software_engineer);
                updateStats('ds', data.data_scientist);

                createChart('se-chart', data.software_engineer);
                createChart('ds-chart', data.data_scientist);

            } catch (error) {
                console.error('Error loading data:', error);
            }
        }

        function updateStats(prefix, stats) {
            document.getElementById(`${prefix}-count`).textContent = stats.count;
            document.getElementById(`${prefix}-avg`).textContent = stats.avg_salary.toLocaleString();
            document.getElementById(`${prefix}-median`).textContent = stats.median_salary.toLocaleString();
            document.getElementById(`${prefix}-min`).textContent = stats.salary_range_min.toLocaleString();
            document.getElementById(`${prefix}-max`).textContent = stats.salary_range_max.toLocaleString();
        }

        function createChart(canvasId, stats) {
            const ctx = document.getElementById(canvasId).getContext('2d');
            new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: ['25th Percentile', 'Median', '75th Percentile', 'Average'],
                    datasets: [{
                        label: 'Salary ($)',
                        data: [stats.percentile_25, stats.median_salary, stats.percentile_75, stats.avg_salary],
                        backgroundColor: ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4'],
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    scales: {
                        y: {
                            beginAtZero: false,
                            ticks: {
                                callback: function(value) {
                                    return '$' + value.toLocaleString();
                                }
                            }
                        }
                    }
                }
            });
        }

        // Load data when page loads
        loadBenchmarkData();

        // Refresh data every 30 seconds
        setInterval(loadBenchmarkData, 30000);
    </script>
</body>
</html>

Production Deployment

Step 11: Configure Production Deployment

Edit deployment/production.toml:

[target.production]
type = "cloud"
provider = "aws"
region = "us-west-2"
instance_type = "c5.xlarge"

[mpc]
parties = 10
threshold = 3
field = "bls12-381"
protocol = "honeybadger"

[security]
attestation = true
encrypted_communication = true
key_management = "hsm"
audit_logging = true

[scaling]
auto_scaling = true
min_nodes = 5
max_nodes = 20
target_cpu_utilization = 70

[monitoring]
metrics = true
alerting = true
log_level = "info"

[compliance]
data_retention_days = 90
privacy_reports = true
gdpr_compliance = true

Step 12: Deploy to Production

# Build optimized release
stoffel build --release

# Deploy to production
stoffel deploy --target production --config deployment/production.toml

# Verify deployment
stoffel status --env production

# Monitor the deployment
stoffel logs --env production --follow

Key Learnings

Congratulations! You've built a complete privacy-preserving salary benchmarking system. Here's what this project demonstrates:

Privacy-First Design

  • Individual salaries never leave each company's control
  • Only aggregate statistics are computed and revealed
  • Minimum data requirements prevent statistical attacks
  • All computation happens on encrypted/secret-shared data

Production-Ready Features

  • Comprehensive error handling and input validation
  • Scalable MPC deployment with auto-scaling
  • Monitoring and alerting for production use
  • Compliance features for regulatory requirements

Developer Experience

  • Clean StoffelLang code with modular design
  • Comprehensive test suite including performance tests
  • Multiple integration options (Python, Web)
  • Easy deployment and configuration management

Next Steps

Now that you've built your first MPC project:

  1. Explore Advanced Features: Learn about advanced development workflows
  2. Optimize Performance: Understand VM optimization techniques
  3. Production Deployment: Deploy to real MPC networks
  4. Community Templates: Explore more use case templates

Real-World Applications

This same pattern can be applied to many privacy-preserving use cases:

  • Healthcare: Multi-hospital research without sharing patient data
  • Finance: Risk assessment across banks without exposing portfolios
  • Marketing: Cross-company analytics without sharing customer data
  • Government: Inter-agency intelligence without data exposure
  • Supply Chain: Collaborative optimization without revealing trade secrets

The Stoffel framework makes all of these applications achievable with the same development patterns you've learned here!

Stoffel CLI Overview

The Stoffel CLI is a comprehensive command-line interface that provides everything you need to develop, build, and deploy privacy-preserving applications using secure Multi-Party Computation (MPC).

Design Philosophy

The Stoffel CLI is designed with the following principles:

  • Developer-Friendly: Intuitive commands that follow familiar patterns from tools like cargo and npm
  • Template-Driven: Project templates for different use cases and programming languages
  • Integrated Workflow: Seamless integration between development, compilation, and deployment
  • Extensible: Plugin system for future enhancements and community contributions

Core Commands

Project Management

# Initialize new projects
stoffel init my-project                    # Default StoffelLang project
stoffel init --template python webapp      # Python integration template
stoffel init --lib crypto-utils           # Create a library project
stoffel init --interactive                # Interactive project setup

Compilation

# Compile StoffelLang programs
stoffel compile                            # Compile all files in src/
stoffel compile src/main.stfl              # Compile specific file
stoffel compile --binary                   # Generate VM-compatible binaries
stoffel compile -O3                        # Maximum optimization

Development

# Development server with hot reloading
stoffel dev                                # Default: 5 parties, port 8080
stoffel dev --parties 7 --port 3000       # Custom configuration
stoffel dev --field bn254                 # Different cryptographic field

Building and Deployment

# Build for different targets
stoffel build                              # Debug build
stoffel build --release                    # Production build
stoffel build --target wasm               # WebAssembly target

# Deploy to various environments
stoffel deploy --target tee               # TEE deployment
stoffel deploy --env production           # Production environment

Available Templates

The CLI provides templates for different development scenarios:

Language-Specific Templates

  • python: Full Python SDK integration with Poetry and pytest
  • rust: Rust FFI integration with StoffelVM (development skeleton)
  • typescript: TypeScript/Node.js client integration
  • solidity: Smart contracts with MPC result verification

Use-Case Templates

  • web3-auction: Private auction implementation
  • web3-voting: Secure voting system
  • web-healthcare: Healthcare data privacy
  • web-fintech: Financial computation privacy
  • desktop-messaging: Secure messaging application

Project Structure

When you create a new project, the CLI generates a standard structure:

my-mpc-project/
├── Stoffel.toml              # Project configuration
├── src/                      # StoffelLang source files
│   ├── main.stfl            # Main program entry point
│   └── lib.stfl             # Library functions (for --lib projects)
├── tests/                   # Test files
│   └── integration.stfl     # Integration tests
└── README.md               # Project documentation

Python Template Structure

For Python integration projects:

my-python-project/
├── Stoffel.toml             # Stoffel configuration
├── pyproject.toml           # Poetry configuration
├── src/
│   ├── main.py             # Python implementation
│   └── secure_computation.stfl  # StoffelLang program
├── tests/
│   └── test_main.py        # Python tests
└── README.md

Configuration

Stoffel.toml

The main configuration file for Stoffel projects:

[package]
name = "my-secure-app"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2024"

[mpc]
protocol = "honeybadger"
parties = 5
threshold = 1
field = "bls12-381"

[build]
optimization_level = 2
target = "vm"
output_dir = "build"

[dev]
hot_reload = true
simulation_mode = true
port = 8080

[dependencies]
# Future: Package dependencies will be listed here

MPC Configuration

The CLI supports configurable MPC parameters:

  • Parties: Number of parties in the MPC computation (minimum 5 for security)
  • Threshold: Maximum number of corrupted parties = (parties - 1) / 3
  • Cryptographic Fields: BLS12-381 (default), BN254, Secp256k1, Prime61
  • Protocol: Currently HoneyBadger MPC (more protocols planned)

Development Server Features

The stoffel dev command provides:

  • Hot Reloading: Automatic recompilation and restart when files change
  • MPC Simulation: Local simulation of multi-party computation for testing
  • Debug Interface: Web interface for debugging MPC execution
  • Live Logs: Real-time logs from all simulated parties
  • Performance Metrics: Timing and communication overhead analysis

Help System

The CLI provides comprehensive help for all commands:

stoffel --help                    # Main help
stoffel init --help               # Command-specific help
stoffel compile --binary --help   # Flag-specific help

Future Features

Planned enhancements for the CLI:

  • Package Manager: stoffel add and stoffel publish for dependency management
  • Testing Framework: stoffel test with MPC-specific test patterns
  • Deployment Tools: Enhanced deployment to cloud providers and Kubernetes
  • Plugin System: Community plugins for specialized workflows
  • IDE Integration: Language server protocol support for editors

Examples

Quick Start

# Create and run a simple MPC project
stoffel init hello-mpc
cd hello-mpc
stoffel dev

# In another terminal
curl http://localhost:8080/execute

Python Integration

# Create Python project with MPC
stoffel init secure-analytics --template python
cd secure-analytics

# Install Python dependencies
poetry install

# Start development
stoffel dev --parties 7

Production Deployment

# Build optimized release
stoffel build --release --target production

# Deploy to TEE environment
stoffel deploy --target tee --config production.toml

Next Steps

Project Management

Development Workflow

Building and Deployment

StoffelLang Overview

StoffelLang is a modern programming language designed specifically for secure Multi-Party Computation (MPC) applications. With syntax inspired by Rust, Python, and JavaScript, it provides a familiar development experience while offering powerful features for privacy-preserving computation.

Design Goals

StoffelLang is designed with the following principles:

  • Familiar Syntax: Draws from popular languages to reduce learning curve
  • Type Safety: Strong static typing with type inference for reliability
  • MPC Native: Built-in support for secret and public data distinctions
  • Performance: Compiles to efficient StoffelVM bytecode
  • Developer Experience: Clear error messages and tooling integration

Key Features

Modern Language Features

  • Static Typing: Strong type system with inference to catch errors early
  • Pattern Matching: Powerful pattern matching for control flow
  • Closures: First-class functions with lexical scoping
  • Memory Safety: Automatic memory management without garbage collection overhead
  • Generics: Parametric polymorphism for reusable code

MPC-Specific Features

  • Secret Types: Native support for secret type annotations
  • Reveal Operations: Explicit operations for transitioning from secret to public
  • Protocol Agnostic: Works with different MPC protocol backends
  • Optimized Compilation: Generates efficient MPC-aware bytecode

Syntax Overview

Basic Syntax

# Variables and types
let x: int64 = 42
let y = 3.14  # Type inference
let name = "Stoffel"
let is_active = true

# Functions
proc add(a: int64, b: int64): int64 =
  return a + b

# Control flow
if x > 0:
  print("Positive")
else:
  print("Non-positive")

# Loops
for i in 0..10:
  print("Count: " + $i)

MPC-Specific Syntax

# Secret types
proc secure_add(a: secret int64, b: secret int64): secret int64 =
  return a + b

# Mixed computation
proc threshold_check(secret_value: secret int64, threshold: int64): secret bool =
  return secret_value > threshold

# Reveal operations (conceptual - actual implementation varies)
proc main() =
  let secret_sum = secure_add(25, 17)
  print("Computation completed securely")

Advanced Features

# Type definitions
type Person = object
  name: string
  age: int64
  is_secret: bool

# Object creation
let alice = Person(
  name: "Alice",
  age: 25,
  is_secret: false
)

# Enum definitions (planned)
type Status = enum
  Active
  Inactive
  Pending

Type System

Primitive Types

  • int64: 64-bit signed integers (primary integer type)
  • bool: Boolean values (true, false)
  • string: UTF-8 strings
  • nil: Null/empty value

Collection Types

  • Objects: Structured data with named fields
  • Enums: Enumerated types with named variants
  • Lists: Dynamic arrays (planned)
  • Tuples: Fixed-size heterogeneous collections (planned)

Secret Types

Any type can be made secret by prefixing with secret:

let public_value: int64 = 42
let secret_value: secret int64 = 42
let secret_name: secret string = "Alice"

Function Types

# Function definitions
proc add(a: int64, b: int64): int64 =
  return a + b

proc multiply(x: int64, y: int64): int64 =
  return x * y

# Functions can call other functions
proc calculate(a: int64, b: int64): int64 =
  let sum = add(a, b)
  let product = multiply(a, b)
  return sum + product

Compilation Process

StoffelLang follows a multi-stage compilation process:

Source (.stfl) → Lexer → Parser → Type Checker → Code Generator → Bytecode (.stfbin)

Compilation Stages

  1. Lexical Analysis: Tokenizes source code
  2. Parsing: Builds Abstract Syntax Tree (AST)
  3. Type Checking: Verifies type correctness and infers types
  4. Optimization: Applies various optimization passes
  5. Code Generation: Generates StoffelVM bytecode

Optimization Levels

# Different optimization levels
stoffel compile source.stfl -O0    # No optimization (debug)
stoffel compile source.stfl -O1    # Basic optimization
stoffel compile source.stfl -O2    # Standard optimization
stoffel compile source.stfl -O3    # Maximum optimization

Integration with StoffelVM

StoffelLang compiles to StoffelVM bytecode, which includes:

  • Rich Type Information: Preserves type metadata for runtime
  • Function Definitions: Complete function metadata and instructions
  • Constant Pools: Efficient storage for literals and constants
  • Debug Information: Line numbers and variable names for debugging

Binary Format

The compiler generates .stfbin files that contain:

┌─────────────────┐
│   File Header   │
├─────────────────┤
│  Type Metadata  │
├─────────────────┤
│   Constant Pool │
├─────────────────┤
│   Function Defs │
├─────────────────┤
│   Bytecode      │
├─────────────────┤
│  Debug Info     │
└─────────────────┘

Development Tools

Compiler CLI

# Basic compilation
stoffel compile source.stfl

# Generate VM-compatible binary
stoffel compile source.stfl --binary

# Enable optimizations
stoffel compile source.stfl --binary -O2

# Print intermediate representations
stoffel compile source.stfl --print-ir

Integration with Stoffel CLI

The StoffelLang compiler is integrated with the main Stoffel CLI:

# Compile via Stoffel CLI
stoffel compile src/main.stfl

# Compile with optimizations
stoffel compile src/main.stfl --binary -O3

# Development workflow
stoffel compile src/main.stfl --binary --output app.stfbin
stoffel-run app.stfbin main

Examples

Hello World

proc main() =
  print("Hello, world!")

Secure Addition

proc secure_add(a: secret int64, b: secret int64): secret int64 =
  return a + b

proc main() =
  let result = secure_add(25, 17)
  print("Secure addition completed")

Complex Data Structures

type Person = object
  name: string
  age: secret int64
  email: string

proc process_person(person: Person): bool =
  # Note: Age comparison would need special MPC operations
  return true  # Simplified for example

proc main() =
  let alice = Person(
    name: "Alice",
    age: secret(25),
    email: "alice@example.com"
  )

  let is_adult = process_person(alice)
  print("Person processed: " + $is_adult)

Basic Computation

proc calculate_total(base: int64, multiplier: int64): int64 =
  return base * multiplier

proc main() =
  let base_value: int64 = 100
  let factor: int64 = 3
  let total = calculate_total(base_value, factor)
  print("Total: " + $total)

Future Features

Planned enhancements for StoffelLang:

  • Pattern Matching: Powerful pattern matching for complex data
  • Generics: Parametric polymorphism for reusable code
  • Async/Await: Asynchronous programming support
  • Macros: Compile-time code generation
  • Package System: Module imports and dependency management
  • Standard Library: Comprehensive built-in functions and types

Language Server

A Language Server Protocol (LSP) implementation is planned to provide:

  • Syntax Highlighting: Rich syntax highlighting in editors
  • Error Reporting: Real-time error checking and suggestions
  • Auto-completion: Intelligent code completion
  • Go-to Definition: Navigate to symbol definitions
  • Refactoring: Automated code refactoring tools

Next Steps

To learn more about StoffelLang:

Syntax and Examples

This page provides a comprehensive guide to StoffelLang syntax, featuring practical examples and detailed explanations of the language's features.

Basic Elements

Comments

StoffelLang uses # for comments:

# This is a single-line comment
let x = 42  # Inline comment

# Multi-line comments can be created
# by using multiple single-line comments

Identifiers and Keywords

Valid identifiers:

  • Must start with a letter or underscore
  • Can contain letters, numbers, and underscores
  • Case-sensitive
let my_variable = 10
let _private_value = "secret"
let camelCase = true
let snake_case_name = "Alice"

Reserved keywords:

let var proc type object enum
if else elif while for in
return yield break continue
true false nil secret discard

Variables and Types

Variable Declarations

StoffelLang supports immutable (let) and mutable (var) variables:

# Immutable variables
let name: string = "Alice"
let age: int64 = 25
let is_active = true  # Type inference

# Mutable variables
var counter: int64 = 0
var status = "pending"  # Type inference

Type Annotations

Explicit type annotations use colon syntax:

let count: int64 = 100
let message: string = "Hello"
let flag: bool = false
let empty: nil = nil

Type Inference

StoffelLang can infer types from context:

let inferred_int = 42        # int64
let inferred_string = "text" # string
let inferred_bool = true     # bool

Primitive Types

Integer Types

StoffelLang primarily uses int64:

let small_number: int64 = 10
let large_number: int64 = 9223372036854775807
let negative: int64 = -42

Boolean Type

let is_ready: bool = true
let is_complete: bool = false

# Boolean operations
let result = true and false  # false
let combined = true or false # true
let negated = not true       # false

String Type

let greeting: string = "Hello, world!"
let empty_string: string = ""
let multiline = "First line\nSecond line"

# String concatenation
let full_name = "Alice" + " " + "Smith"
let message = "Count: " + $42  # Convert int to string with $

Nil Type

let nothing: nil = nil
let maybe_value = nil  # Type inferred as nil

Secret Types

The secret keyword creates MPC-aware types:

# Secret primitive types
let secret_age: secret int64 = 25
let secret_name: secret string = "Bob"
let secret_flag: secret bool = true

# Secret values in computations
proc secure_comparison(a: secret int64, b: secret int64): secret bool =
  return a > b

# Mixed public/secret operations
proc threshold_check(secret_value: secret int64, public_threshold: int64): secret bool =
  return secret_value >= public_threshold

Functions

Function Definitions

Functions use the proc keyword:

# Basic function
proc greet(name: string): string =
  return "Hello, " + name

# Function with multiple parameters
proc add(a: int64, b: int64): int64 =
  return a + b

# Function without return value (implicit nil return)
proc log_message(msg: string) =
  print(msg)

# Function with secret parameters
proc secure_multiply(a: secret int64, b: secret int64): secret int64 =
  return a * b

Function Calls

# Basic function calls
let result = add(10, 20)
let greeting = greet("Alice")

# Nested function calls
let complex_result = add(add(1, 2), add(3, 4))

# Secret function calls
let secret_result = secure_multiply(secret(5), secret(6))

Functions with Local Variables

proc calculate_area(length: int64, width: int64): int64 =
  let area = length * width
  let formatted_msg = "Area calculated: " + $area
  print(formatted_msg)
  return area

Control Flow

If Statements

# Basic if statement
if age >= 18:
  print("Adult")

# If-else
if temperature > 30:
  print("Hot")
else:
  print("Not hot")

# If-elif-else
if score >= 90:
  print("A grade")
elif score >= 80:
  print("B grade")
elif score >= 70:
  print("C grade")
else:
  print("Below C grade")

If Expressions

If statements can be used as expressions:

let status = if age >= 18: "adult" else: "minor"
let max_value = if a > b: a else: b

While Loops

# Basic while loop
var count = 0
while count < 10:
  print("Count: " + $count)
  count = count + 1

# While with complex condition
var running = true
var attempts = 0
while running and attempts < 5:
  # Do something
  attempts = attempts + 1
  if attempts >= 3:
    running = false

For Loops

# Range-based for loops
for i in 0..10:
  print("Number: " + $i)

# For loop with step (conceptual - syntax may vary)
for i in 0..20:
  if i % 2 == 0:
    print("Even: " + $i)

Data Structures

Object Types

# Object type definition
type Person = object
  name: string
  age: int64
  email: string
  is_active: bool

# Object with secret fields
type SecurePerson = object
  name: string
  age: secret int64
  salary: secret int64
  public_id: int64

Object Creation and Access

# Creating objects
let alice = Person(
  name: "Alice Smith",
  age: 30,
  email: "alice@example.com",
  is_active: true
)

# Accessing fields
let person_name = alice.name
let person_age = alice.age

# Creating objects with secret fields
let secure_employee = SecurePerson(
  name: "Bob Jones",
  age: secret(35),
  salary: secret(75000),
  public_id: 12345
)

Nested Objects

type Address = object
  street: string
  city: string
  country: string

type Employee = object
  personal: Person
  address: Address
  employee_id: int64

let employee = Employee(
  personal: Person(
    name: "Carol Davis",
    age: 28,
    email: "carol@company.com",
    is_active: true
  ),
  address: Address(
    street: "123 Main St",
    city: "Tech City",
    country: "USA"
  ),
  employee_id: 98765
)

# Accessing nested fields
let employee_name = employee.personal.name
let employee_city = employee.address.city

Enum Types (Planned)

# Basic enum
type Status = enum
  Active
  Inactive
  Pending
  Suspended

# Enum with values
type Priority = enum
  Low = 1
  Medium = 2
  High = 3
  Critical = 4

# Using enums
let current_status = Status.Active
let task_priority = Priority.High

Operators

Arithmetic Operators

let a = 10
let b = 3

let sum = a + b      # 13
let difference = a - b  # 7
let product = a * b     # 30
let quotient = a / b    # 3 (integer division)
let remainder = a % b   # 1

Comparison Operators

let x = 10
let y = 20

let equal = x == y        # false
let not_equal = x != y    # true
let less_than = x < y     # true
let less_equal = x <= y   # true
let greater_than = x > y  # false
let greater_equal = x >= y # false

Logical Operators

let a = true
let b = false

let logical_and = a and b  # false
let logical_or = a or b    # true
let logical_not = not a    # false

String Operations

let first = "Hello"
let second = "World"

let combined = first + " " + second  # "Hello World"
let with_number = "Count: " + $42    # "Count: 42"

Advanced Features

Working with Secret Types

# Secret arithmetic
proc secure_calculation(a: secret int64, b: secret int64, c: int64): secret int64 =
  let secret_sum = a + b
  let mixed_operation = secret_sum * c  # Public value used with secret
  return mixed_operation

# Secret comparisons
proc secure_threshold(value: secret int64, threshold: int64): secret bool =
  return value > threshold

# Multiple secret operations
proc complex_secure_calc(
  secret_a: secret int64,
  secret_b: secret int64,
  public_factor: int64
): secret int64 =
  let temp1 = secret_a + secret_b
  let temp2 = secret_a * secret_b
  let result = (temp1 + temp2) * public_factor
  return result

Error Handling (Planned)

# Try-catch blocks (future feature)
try:
  let result = risky_operation()
  print("Success: " + $result)
catch error:
  print("Error occurred: " + error.message)

Pattern Matching (Planned)

# Match expressions (future feature)
let result = match status:
  Status.Active: "Currently active"
  Status.Inactive: "Not active"
  Status.Pending: "Waiting for approval"
  _: "Unknown status"

Best Practices

Naming Conventions

# Use snake_case for variables and functions
let user_name = "alice"
let max_retry_count = 5

proc calculate_total_cost(base_price: int64, tax_rate: int64): int64 =
  return base_price + (base_price * tax_rate / 100)

# Use PascalCase for types
type UserAccount = object
  user_id: int64
  account_balance: secret int64

Type Safety

# Prefer explicit types for public interfaces
proc public_api(user_id: int64, amount: secret int64): bool =
  # Implementation
  return true

# Use type inference for local variables
proc internal_calculation() =
  let temp = 42  # Type inferred as int64
  let message = "Processing"  # Type inferred as string

Secret Type Usage

# Clearly distinguish between public and secret data
proc process_transaction(
  public_user_id: int64,
  secret_amount: secret int64,
  public_currency: string
): secret bool =
  # Only secret operations on secret data
  let is_valid_amount = secret_amount > 0
  return is_valid_amount

# Avoid unnecessary secret wrapping
proc calculate_fee(amount: int64): int64 =  # Public calculation
  return amount * 5 / 100

proc apply_secret_fee(secret_amount: secret int64): secret int64 =
  let fee_rate = 5  # Public constant
  return secret_amount * fee_rate / 100  # Secret result

Function Organization

# Small, focused functions
proc validate_age(age: int64): bool =
  return age >= 0 and age <= 150

proc validate_email(email: string): bool =
  # Simplified validation
  return email.length > 0

proc create_user(name: string, age: int64, email: string): Person =
  # Use validation functions
  if not validate_age(age):
    # Error handling (simplified)
    print("Invalid age")

  if not validate_email(email):
    print("Invalid email")

  return Person(
    name: name,
    age: age,
    email: email,
    is_active: true
  )

Common Patterns

Data Processing

proc process_user_data(user: Person): string =
  let age_category = if user.age < 18:
    "minor"
  elif user.age < 65:
    "adult"
  else:
    "senior"

  let status_text = if user.is_active: "active" else: "inactive"

  return user.name + " (" + age_category + ", " + status_text + ")"

Secret Computation Patterns

# Secure comparison with public result indication
proc secure_age_check(secret_age: secret int64, min_age: int64): bool =
  let meets_requirement = secret_age >= min_age
  # In practice, this would use proper MPC reveal operations
  return true  # Simplified for syntax example

# Secure aggregation pattern
proc secure_sum(values: [secret int64; 5]): secret int64 =
  var total: secret int64 = 0
  for i in 0..5:
    # Note: Array indexing syntax may vary in implementation
    # This is a conceptual example
    total = total + values[i]
  return total

This syntax guide covers the current StoffelLang implementation and provides a foundation for understanding the language's structure and capabilities.

Compilation

This page explains the StoffelLang compilation process, from source code to executable bytecode, including optimization techniques and debugging capabilities.

Overview

StoffelLang uses a multi-stage compilation pipeline that transforms human-readable source code into efficient bytecode for the StoffelVM. The compiler is designed to provide excellent error messages, strong type checking, and optimizations specific to MPC computations.

Compilation Pipeline

Stage 1: Lexical Analysis

The lexer tokenizes the source code, breaking it into meaningful tokens:

Source: let x: int64 = 42
Tokens: [LET, IDENTIFIER("x"), COLON, IDENTIFIER("int64"), ASSIGN, INT_LITERAL(42)]

Key Features:

  • Indentation-based: Uses 2-space indentation (tabs not allowed)
  • Unicode support: Full UTF-8 string and identifier support
  • Error recovery: Continues parsing after errors to find more issues

Stage 2: Parsing

The parser builds an Abstract Syntax Tree (AST) from the token stream:

AST Node: VariableDeclaration {
  name: "x",
  type_annotation: Some(Identifier("int64")),
  value: Some(Literal(Int(42))),
  is_mutable: false,
  is_secret: false,
  location: SourceLocation { line: 1, column: 1 }
}

Parser Features:

  • Recursive descent: Predictable parsing with clear error messages
  • Location tracking: Every AST node includes source location
  • Error recovery: Attempts to continue parsing after syntax errors

Stage 3: Semantic Analysis

The semantic analyzer performs type checking and builds the symbol table:

Type Checking:

# This would produce a type error
let name: string = 42  # Error: Cannot assign int64 to string

# This works correctly
let age: int64 = 42    # OK: Types match

Symbol Resolution:

proc add(a: int64, b: int64): int64 =
  return a + b  # Resolves 'a' and 'b' to parameters

let result = add(10, 20)  # Resolves 'add' to function definition

Stage 4: Code Generation

Generates StoffelVM bytecode from the validated AST:

StoffelLang:           Bytecode:
let x: int64 = 42      LDI R0, 42
                      STORE x, R0

proc add(a, b):        FUNCTION add:
  return a + b           LOAD R0, a
                        LOAD R1, b
                        ADD R0, R0, R1
                        RET R0

Using the Compiler

Basic Compilation

# Compile a single file
stoffel compile src/main.stfl

# Compile to VM-compatible binary
stoffel compile src/main.stfl --binary --output program.stfbin

# Compile all files in src/
stoffel compile

Compilation Options

Optimization Levels

# No optimization (fastest compilation, good for debugging)
stoffel compile src/main.stfl -O0

# Basic optimizations (balanced)
stoffel compile src/main.stfl -O1

# Standard optimizations (recommended for production)
stoffel compile src/main.stfl -O2

# Maximum optimizations (slowest compilation, best performance)
stoffel compile src/main.stfl -O3

Output Formats

# Default bytecode format
stoffel compile src/main.stfl

# VM-compatible binary (for execution)
stoffel compile src/main.stfl --binary --output app.stfbin

# Specify custom output location
stoffel compile src/main.stfl --output custom/path/program.stfbin

Debug Information

# Include debug symbols
stoffel compile src/main.stfl --debug

# Print intermediate representations
stoffel compile src/main.stfl --print-ir

# Verbose compilation output
stoffel compile src/main.stfl --verbose

Optimization Techniques

Constant Folding

The compiler evaluates constant expressions at compile time:

# Source code
let result = 2 + 3 * 4

# Optimized to
let result = 14

Dead Code Elimination

Removes unreachable code:

# Source code
proc example(flag: bool) =
  if true:
    print("Always executed")
  else:
    print("Never executed")  # Removed by optimizer

# Optimized to
proc example(flag: bool) =
  print("Always executed")

Function Inlining

Small functions may be inlined at call sites:

# Source code
proc square(x: int64): int64 =
  return x * x

let result = square(5)

# May be optimized to
let result = 5 * 5

Secret Operation Optimization

Special optimizations for MPC operations:

# Source code
let a: secret int64 = 10
let b: secret int64 = 20
let sum = a + b
let product = a * b

# Compiler may batch secret operations for efficiency

Error Handling

Syntax Errors

Clear error messages with source locations:

Error: Unexpected token 'let'
  --> src/main.stfl:5:3
   |
 5 |   let x = 42
   |   ^^^ Expected expression, found 'let'
   |
Help: Variable declarations must be at the top level of a block

Type Errors

Detailed type mismatch information:

Error: Type mismatch in assignment
  --> src/main.stfl:8:12
   |
 8 | let name: string = 42
   |           ------   ^^ Expected 'string', found 'int64'
   |           |
   |           Variable declared as 'string' here
   |
Help: Convert the integer to string: "42" or $42

Semantic Errors

Context-aware error messages:

Error: Cannot find value 'undefined_var' in this scope
  --> src/main.stfl:12:15
   |
12 |   return undefined_var + 10
   |                ^^^^^^^^^^^^
   |
Help: Did you mean 'defined_var'? (defined at line 3)

Intermediate Representations

Viewing IR with --print-ir

stoffel compile src/main.stfl --print-ir

Output includes:

  1. Tokens: Lexical analysis output
  2. AST: Parsed syntax tree
  3. Type Information: Resolved types and symbols
  4. Bytecode: Generated VM instructions

Example IR Output

=== TOKENS ===
LET(1:1) IDENTIFIER("x", 1:5) COLON(1:6) IDENTIFIER("int64", 1:8) ASSIGN(1:14) INT_LITERAL(42, 1:16)

=== AST ===
VariableDeclaration {
  name: "x",
  type_annotation: Some(TypeRef("int64")),
  value: Some(IntLiteral(42)),
  is_mutable: false,
  location: SourceLocation(1:1)
}

=== BYTECODE ===
Constants:
  0: Int(42)

Instructions:
  0000: LDC R0, 0     ; Load constant 42
  0001: STORE x, R0   ; Store in variable x

Binary Format

File Structure

StoffelLang produces .stfbin files with the following structure:

┌─────────────────┐
│   Magic Number  │  4 bytes: "STFL"
├─────────────────┤
│   Version       │  4 bytes: Format version
├─────────────────┤
│   Metadata      │  Variable: Type information
├─────────────────┤
│   Constants     │  Variable: Constant pool
├─────────────────┤
│   Functions     │  Variable: Function definitions
├─────────────────┤
│   Instructions  │  Variable: Bytecode instructions
├─────────────────┤
│   Debug Info    │  Variable: Source locations
└─────────────────┘

Binary Inspection

# Disassemble a compiled binary
stoffel compile program.stfbin --disassemble

# Output shows human-readable bytecode
FUNCTION main:
  Constants: [Int(42), String("Hello")]
  Instructions:
    0000: LDC R0, 0      ; Load 42
    0001: LDC R1, 1      ; Load "Hello"
    0002: CALL print     ; Call print function
    0003: RET R0         ; Return

Compilation Workflow

Single File Compilation

# 1. Compile source to binary
stoffel compile src/main.stfl --binary --output app.stfbin

# 2. Run the compiled program
stoffel-run app.stfbin main

# 3. Debug if needed
stoffel-run app.stfbin main --trace-instr

Multi-File Projects

# 1. Compile all files
stoffel compile

# 2. The compiler automatically handles dependencies
# Files are compiled in dependency order

# 3. Single binary output contains all functions

Development Workflow

# 1. Write code
# edit src/main.stfl

# 2. Quick compile check
stoffel compile src/main.stfl

# 3. Full compile and test
stoffel compile src/main.stfl --binary --output test.stfbin
stoffel-run test.stfbin main

# 4. Debug compilation issues
stoffel compile src/main.stfl --print-ir

# 5. Production build
stoffel compile src/main.stfl --binary -O3 --output production.stfbin

Performance Considerations

Compilation Speed

Optimization LevelCompile TimeRuntime Performance
-O0FastestBasic
-O1FastGood
-O2MediumBetter
-O3SlowestBest

Memory Usage

  • Compiler memory: Scales with source code size and complexity
  • Binary size: Optimizations can reduce final binary size
  • Runtime memory: Efficient bytecode reduces VM memory usage

Secret Type Optimization

Special considerations for MPC operations:

# Expensive: Many individual secret operations
proc inefficient(a: secret int64, b: secret int64): secret int64 =
  let temp1 = a + 1
  let temp2 = b + 1
  let temp3 = temp1 + temp2
  return temp3 + 1

# Better: Batched operations where possible
proc efficient(a: secret int64, b: secret int64): secret int64 =
  return a + b + 2  # Compiler can optimize this

Troubleshooting

Common Compilation Errors

"Tabs are not allowed"

# Fix: Use 2 spaces instead of tabs
# Bad:
	let x = 42
# Good:
  let x = 42

"Indentation error"

# Fix: Consistent 2-space indentation
proc example() =
  if true:
    print("Correct indentation")

"Type mismatch"

# Fix: Ensure types match
let age: int64 = 25      # Correct
let name: string = "Bob" # Correct
# let wrong: string = 42  # Error

Debugging Tips

  1. Use --print-ir to see what the compiler generated
  2. Start with -O0 for debugging, optimize later
  3. Check types explicitly rather than relying on inference
  4. Use --verbose to see detailed compilation steps

Performance Issues

  1. Profile with --trace-instr during execution
  2. Try different optimization levels
  3. Review generated bytecode with --disassemble
  4. Minimize secret operations where possible

Integration with Development Tools

Editor Integration

# Generate compilation database for editors
stoffel compile --export-compile-commands

# This creates compile_commands.json for IDE integration

Build Systems

# Makefile integration
%.stfbin: %.stfl
	stoffel compile $< --binary --output $@

# Used as:
# make program.stfbin

Continuous Integration

#!/bin/bash
# CI script for StoffelLang projects

# Compile all files
stoffel compile

# Compile with different optimization levels
stoffel compile --binary -O0 --output debug.stfbin
stoffel compile --binary -O3 --output release.stfbin

# Run basic tests
stoffel-run debug.stfbin main

Advanced Topics

Cross-Compilation

Currently, StoffelLang generates platform-independent bytecode that runs on any StoffelVM instance.

Linking (Future)

Planned support for linking multiple compiled modules:

# Compile library
stoffel compile --lib src/math.stfl --output math.stflib

# Link with main program
stoffel compile src/main.stfl --link math.stflib --output app.stfbin

Plugin Architecture (Future)

Support for compiler plugins to extend functionality:

# Custom optimization passes
stoffel compile --plugin my_optimizer.so src/main.stfl

# Custom code generators
stoffel compile --target wasm --plugin wasm_gen.so src/main.stfl

This compilation guide provides comprehensive information about building StoffelLang programs and optimizing them for the StoffelVM runtime environment.

StoffelVM Overview

StoffelVM is a register-based virtual machine specifically designed and optimized for secure Multi-Party Computation (MPC). It provides a flexible and efficient foundation for executing MPC protocols while maintaining protocol agnosticism.

Key Features

Register-Based Architecture

Unlike stack-based VMs, StoffelVM uses a register-based design that enables:

  • Easy Optimization: Direct mapping to physical hardware registers
  • Efficient Compilation: Cleaner code generation from high-level languages
  • MPC Optimization: Separate handling of clear and secret values

Rich Type System

StoffelVM supports a comprehensive set of value types:

  • Primitives: i64 integers, fixed-point floats, booleans, strings
  • Collections: Arrays and objects with dynamic sizing
  • Functions: Closures with true lexical scoping and upvalue capture
  • Foreign Objects: FFI integration with host language objects
  • Unit Type: Void/null values for control flow

MPC Integration

The VM is designed with MPC in mind:

  • Clear/Secret Separation: Distinct register spaces for public and private data
  • Protocol Agnosticism: Works with different MPC protocol implementations
  • Efficient Sharing: Optimized handling of secret-shared values

Current Status

🚧 Development Status

StoffelVM is currently functional with some quirks. The core VM operations work well, but full MPC functionality is still in development.

Working Features:

  • ✅ Complete instruction set implementation
  • ✅ Register management and memory operations
  • ✅ Arithmetic and bitwise operations
  • ✅ Control flow (jumps, calls, returns)
  • ✅ Object and array manipulation
  • ✅ Closure system with lexical scoping
  • ✅ Foreign function interface (FFI)
  • ✅ Built-in standard library functions

In Development:

  • 🚧 Full MPC protocol integration
  • 🚧 Automatic memory management/garbage collection
  • 🚧 Exception handling system
  • 🚧 Dynamic library loading/unloading
  • 🚧 Tail call optimization

Architecture Overview

┌─────────────────────────────────────────────────────────┐
│                    StoffelVM                            │
├─────────────────────┬───────────────────────────────────┤
│   Clear Registers   │        Secret Registers          │
│   (Public Data)     │       (Private/Shared Data)      │
├─────────────────────┼───────────────────────────────────┤
│              Instruction Processor                     │
├─────────────────────────────────────────────────────────┤
│                 Memory Management                      │
├─────────────────────┬───────────────────────────────────┤
│   Object Store      │         Array Store             │
├─────────────────────┼───────────────────────────────────┤
│   Closure System    │      Foreign Objects            │
├─────────────────────┴───────────────────────────────────┤
│                    Hook System                         │
│              (Debugging & Protocol Integration)        │
└─────────────────────────────────────────────────────────┘

Value Types

Primitive Types

#![allow(unused)]
fn main() {
Value::Int(i64)           // 64-bit signed integers
Value::Float(i64)         // Fixed-point float representation
Value::Bool(bool)         // Boolean values
Value::String(String)     // UTF-8 strings
Value::Unit               // Unit/void type
}

Complex Types

#![allow(unused)]
fn main() {
Value::Object(usize)      // Object reference (key-value pairs)
Value::Array(usize)       // Array reference (indexed values)
Value::Closure(Arc<Closure>) // Function closure with captured variables
Value::Foreign(usize)     // Foreign object from host language
}

Instruction Set

Memory Operations

LD(dest_reg, stack_offset)    // Load from stack to register
LDI(dest_reg, value)          // Load immediate value
MOV(dest_reg, src_reg)        // Move between registers
PUSHARG(reg)                  // Push register as function argument

Arithmetic Operations

ADD(dest, src1, src2)         // Addition
SUB(dest, src1, src2)         // Subtraction
MUL(dest, src1, src2)         // Multiplication
DIV(dest, src1, src2)         // Division
MOD(dest, src1, src2)         // Modulo

Bitwise Operations

AND(dest, src1, src2)         // Bitwise AND
OR(dest, src1, src2)          // Bitwise OR
XOR(dest, src1, src2)         // Bitwise XOR
NOT(dest, src)                // Bitwise NOT
SHL(dest, src, amount)        // Shift left
SHR(dest, src, amount)        // Shift right

Control Flow

JMP(label)                    // Unconditional jump
JMPEQ(label)                  // Jump if equal
JMPNEQ(label)                 // Jump if not equal
CMP(reg1, reg2)               // Compare registers
CALL(function_name)           // Function call
RET(reg)                      // Return with value

Usage Patterns

Embedding in Applications

The VM is designed to be embedded in larger applications:

use stoffel_vm::core_vm::VirtualMachine;
use stoffel_vm::functions::VMFunction;
use stoffel_vm::instructions::Instruction;
use stoffel_vm::core_types::Value;

fn main() -> Result<(), String> {
    let vm = VirtualMachine::new();

    // Register a function
    let hello_world = VMFunction {
        name: "hello_world".to_string(),
        parameters: vec![],
        upvalues: vec![],
        parent: None,
        register_count: 1,
        instructions: vec![
            Instruction::LDI(0, Value::String("Hello, World!".to_string())),
            Instruction::PUSHARG(0),
            Instruction::CALL("print".to_string()),
            Instruction::RET(0),
        ],
        labels: HashMap::new(),
    };

    vm.register_function(hello_world);

    // Execute the function
    let result = vm.execute("hello_world")?;
    println!("Result: {:?}", result);

    Ok(())
}

CLI Usage

The VM can also be used via the CLI to run compiled programs:

# Build the CLI
cargo build --release -p stoffel-vm

# Run a compiled program
./target/release/stoffel-run path/to/program.stfbin main

Standard Library

StoffelVM includes essential built-in functions:

  • print: Output values to console
  • create_object: Create new objects
  • create_array: Create new arrays
  • get_field/set_field: Object/array field access
  • array_length/array_push: Array operations
  • create_closure/call_closure: Closure operations
  • get_upvalue/set_upvalue: Upvalue management
  • type: Runtime type information

Hook System

The VM provides a configurable hook system for:

  • Instruction Execution: Intercept and monitor individual instructions
  • Register Access: Track register reads and writes
  • Activation Stack: Monitor function calls and returns
  • Memory Operations: Debug object and array operations
  • MPC Integration: Protocol-specific hooks for secret operations

Performance Characteristics

Register-Based Advantages

  • Fewer Instructions: Direct register operations reduce instruction count
  • Better Optimization: Easier to optimize compared to stack machines
  • Hardware Mapping: Natural mapping to CPU registers

MPC Optimizations

  • Separate Register Spaces: Efficient handling of clear vs. secret data
  • Batched Operations: Group operations for better protocol efficiency
  • Memory Layout: Optimized for secret sharing and reconstruction

Integration with Ecosystem

StoffelLang Compilation

The VM executes bytecode generated by the StoffelLang compiler:

StoffelLang (.stfl) → Compiler → Bytecode (.stfb) → StoffelVM

Python SDK Integration

The Python SDK provides high-level bindings to the VM:

from stoffel import StoffelProgram

program = StoffelProgram("secure_add.stfl")
program.compile()
result = program.execute_locally({"a": 25, "b": 17})

MPC Protocol Integration

The VM integrates with MPC protocols for secure computation:

StoffelVM ↔ MPC Protocols ↔ Network Communication

Future Development

Planned enhancements for StoffelVM:

  • Full MPC Integration: Complete protocol integration for secure computation
  • Garbage Collection: Automatic memory management for objects and arrays
  • Exception Handling: Structured error handling and recovery
  • Tail Call Optimization: Efficient recursive function calls
  • Just-In-Time Compilation: Runtime optimization for hot code paths
  • Debugging Tools: Enhanced debugging and profiling capabilities

Next Steps

To learn more about StoffelVM:

Instructions and Types

Using the VM

Built-in Functions

Python SDK Overview

The Stoffel Python SDK provides a clean, high-level interface for integrating Stoffel's secure Multi-Party Computation capabilities into Python applications. It offers a developer-friendly API that abstracts away cryptographic complexity while maintaining clear semantics for public and secret data.

Design Philosophy

The SDK is built around two core principles:

Separation of Concerns

  • StoffelProgram: Handles StoffelLang compilation, VM operations, and execution parameters
  • StoffelClient: Manages MPC network communication, data handling, and result reconstruction

Explicit Data Visibility

The API makes a clear distinction between:

  • Secret Inputs: Private data that gets secret-shared across MPC nodes
  • Public Inputs: Configuration and parameters visible to all nodes

Core Components

StoffelProgram - VM Operations

Responsible for local program management and compilation:

from stoffel import StoffelProgram

# Create and compile a program
program = StoffelProgram("secure_add.stfl")
program.compile(optimize=True)

# Set execution parameters
program.set_execution_params({
    "computation_id": "secure_addition",
    "function_name": "main",
    "expected_inputs": ["a", "b", "threshold"]
})

# Test locally before MPC execution
result = program.execute_locally({"a": 25, "b": 17})

StoffelClient - Network Operations

Handles MPC network communication and data management:

from stoffel import StoffelClient

# Configure MPC network connection
client = StoffelClient({
    "nodes": [
        "http://mpc-node1:9000",
        "http://mpc-node2:9000",
        "http://mpc-node3:9000"
    ],
    "client_id": "client_001",
    "program_id": "secure_addition"
})

# Execute with explicit public/secret inputs
result = await client.execute_with_inputs(
    secret_inputs={"a": 25, "b": 17},      # Private data
    public_inputs={"threshold": 50}        # Public configuration
)

Quick Start

Simple MPC Computation

import asyncio
from stoffel import StoffelProgram, StoffelClient

async def main():
    # 1. Program compilation and setup
    program = StoffelProgram("secure_add.stfl")
    program.compile()
    program.set_execution_params({
        "computation_id": "secure_addition",
        "function_name": "main",
        "expected_inputs": ["a", "b"]
    })

    # 2. MPC network client setup
    client = StoffelClient({
        "nodes": ["http://mpc-node1:9000", "http://mpc-node2:9000", "http://mpc-node3:9000"],
        "client_id": "my_client",
        "program_id": "secure_addition"
    })

    # 3. Execute secure computation
    result = await client.execute_with_inputs(
        secret_inputs={"a": 25, "b": 17}
    )

    print(f"Secure computation result: {result}")
    await client.disconnect()

asyncio.run(main())

Minimal One-Liner Usage

import asyncio
from stoffel import StoffelClient

async def main():
    client = StoffelClient({
        "nodes": ["http://mpc-node1:9000", "http://mpc-node2:9000", "http://mpc-node3:9000"],
        "client_id": "my_client",
        "program_id": "my_secure_program"
    })

    result = await client.execute_with_inputs(
        secret_inputs={"user_data": 123, "private_value": 456},
        public_inputs={"config_param": 100}
    )

    print(f"Result: {result}")
    await client.disconnect()

asyncio.run(main())

API Reference

StoffelProgram

class StoffelProgram:
    def __init__(self, source_file: Optional[str] = None)

    # Compilation and loading
    def compile(self, optimize: bool = True) -> str
    def load_program(self) -> None

    # Execution configuration
    def set_execution_params(self, params: Dict[str, Any]) -> None
    def get_computation_id(self) -> str
    def get_program_info(self) -> Dict[str, Any]

    # Local testing
    def execute_locally(self, inputs: Dict[str, Any]) -> Any

StoffelClient

class StoffelClient:
    def __init__(self, network_config: Dict[str, Any])

    # Recommended API - explicit input types
    async def execute_with_inputs(
        self,
        secret_inputs: Optional[Dict[str, Any]] = None,
        public_inputs: Optional[Dict[str, Any]] = None
    ) -> Any

    # Individual input management
    def set_secret_input(self, name: str, value: Any) -> None
    def set_public_input(self, name: str, value: Any) -> None
    def set_inputs(
        self,
        secret_inputs: Optional[Dict[str, Any]] = None,
        public_inputs: Optional[Dict[str, Any]] = None
    ) -> None

    # Connection management
    async def connect(self) -> None
    async def disconnect(self) -> None
    def is_ready(self) -> bool
    def get_connection_status(self) -> Dict[str, Any]

    # Legacy API (backward compatibility)
    async def execute_program_with_inputs(self, inputs: Dict[str, Any]) -> Any
    def set_private_data(self, name: str, value: Any) -> None
    async def execute_program(self) -> Any

Network Configuration

Direct Node Connection

# Direct connection to known MPC nodes
client = StoffelClient({
    "nodes": [
        "http://mpc-node1:9000",
        "http://mpc-node2:9000",
        "http://mpc-node3:9000"
    ],
    "client_id": "your_client_id",
    "program_id": "your_program_id"
})

Optional Coordinator Integration

# With coordinator for metadata exchange
client = StoffelClient({
    "nodes": [
        "http://mpc-node1:9000",
        "http://mpc-node2:9000",
        "http://mpc-node3:9000"
    ],
    "coordinator_url": "http://coordinator:8080",  # Optional
    "client_id": "your_client_id",
    "program_id": "your_program_id"
})

Usage Patterns

Healthcare Data Privacy

async def secure_health_analysis():
    client = StoffelClient(config)

    result = await client.execute_with_inputs(
        secret_inputs={
            "patient_age": 45,
            "medical_history": encoded_history,
            "test_results": lab_values
        },
        public_inputs={
            "analysis_type": "risk_assessment",
            "threshold_values": risk_thresholds
        }
    )

    return result

Financial Computation

async def secure_credit_score():
    client = StoffelClient(config)

    result = await client.execute_with_inputs(
        secret_inputs={
            "salary": 75000,
            "credit_history": credit_data,
            "debt_ratio": 0.3
        },
        public_inputs={
            "scoring_model": "fico_v9",
            "market_conditions": current_rates
        }
    )

    return result

Multi-Party Auction

async def secure_auction():
    client = StoffelClient(config)

    result = await client.execute_with_inputs(
        secret_inputs={
            "my_bid": 1000,
            "max_budget": 5000
        },
        public_inputs={
            "auction_id": "item_12345",
            "auction_rules": rules_config
        }
    )

    return result

Advanced Features

Low-Level VM Access

For specialized use cases requiring direct VM control:

from stoffel.vm import VirtualMachine, StoffelValue

# Direct VM instantiation
vm = VirtualMachine()

# Register custom foreign functions
def custom_function(arg1, arg2):
    return arg1 * arg2 + 42

vm.register_foreign_function("custom_op", custom_function)

# Execute with arguments
result = vm.execute_with_args("main", [
    StoffelValue.integer(100),
    StoffelValue.string("test")
])

Error Handling

from stoffel.mpc import MPCError, NetworkError, ComputationError

try:
    result = await client.execute_with_inputs(
        secret_inputs={"value": 123},
        public_inputs={"param": 456}
    )
except NetworkError as e:
    print(f"Network issue: {e}")
except ComputationError as e:
    print(f"MPC computation failed: {e}")
except MPCError as e:
    print(f"General MPC error: {e}")

Installation and Setup

Prerequisites

  • Python 3.8 or higher
  • StoffelVM shared library (libstoffel_vm.so or equivalent)
  • StoffelLang compiler (for .stfl compilation)

Installation Options

# With Poetry (recommended)
poetry install

# With pip
pip install stoffel-python-sdk

# Development installation
git clone https://github.com/stoffel-labs/stoffel-python-sdk.git
cd stoffel-python-sdk
poetry install

Examples and Testing

The SDK includes comprehensive examples:

# Simple API demonstration
poetry run python examples/simple_api_demo.py

# Complete architecture example
poetry run python examples/correct_flow.py

# Advanced VM operations
poetry run python examples/vm_example.py

Development Status

Current implementation status:

  • Clean API Design: Proper separation of concerns implemented
  • StoffelProgram: Compilation and VM operations (ready for integration)
  • StoffelClient: Network communication interface (ready for MPC integration)
  • VM Bindings: FFI bindings to StoffelVM
  • 🚧 MPC Network Integration: Awaiting actual MPC service infrastructure
  • 🚧 StoffelLang Integration: Compiler integration in progress
  • 📋 Integration Tests: With actual shared libraries and MPC networks

Architecture Benefits

Clean Separation

  • VM Operations: Isolated in StoffelProgram for local testing and compilation
  • Network Communication: Handled by StoffelClient for MPC operations
  • Clear Boundaries: Easy to understand and extend

Type Safety

  • Explicit Input Types: Clear distinction between secret and public data
  • Runtime Safety: Proper error handling and validation
  • Development Safety: Type hints throughout the codebase

Extensibility

  • Plugin Architecture: Ready for additional protocol backends
  • Foreign Functions: Easy integration with existing Python libraries
  • Modular Design: Components can be used independently

Next Steps

To get started with the Stoffel Python SDK:

Installation

API Reference

Examples

Protocol Overview

Implementation Details

System Architecture

This section provides an overview of the complete Stoffel system architecture and how the various components interact.

Overall System Design

┌─────────────────────────────────────────────────────────────────┐
│                        Stoffel Ecosystem                       │
├─────────────────────────────────────────────────────────────────┤
│  Developer Interface Layer                                     │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │ Stoffel CLI │  │ Python SDK  │  │   IDEs &    │            │
│  │             │  │             │  │  Editors    │            │
│  └─────────────┘  └─────────────┘  └─────────────┘            │
├─────────────────────────────────────────────────────────────────┤
│  Compilation Layer                                             │
│  ┌─────────────┐  ┌─────────────┐                             │
│  │ StoffelLang │  │   Bytecode  │                             │
│  │  Compiler   │→ │  Generator  │                             │
│  └─────────────┘  └─────────────┘                             │
├─────────────────────────────────────────────────────────────────┤
│  Execution Layer                                               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │ StoffelVM   │  │   Runtime   │  │  Standard   │            │
│  │   Core      │  │   System    │  │  Library    │            │
│  └─────────────┘  └─────────────┘  └─────────────┘            │
├─────────────────────────────────────────────────────────────────┤
│  Protocol Layer                                                │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │ MPC Proto-  │  │  Network    │  │ Crypto      │            │
│  │   cols      │  │   Layer     │  │ Primitives  │            │
│  └─────────────┘  └─────────────┘  └─────────────┘            │
└─────────────────────────────────────────────────────────────────┘

Component Interactions

Development Workflow

  1. Project Creation: Stoffel CLI creates project structure with templates
  2. Code Writing: Developers write StoffelLang programs with MPC primitives
  3. Compilation: StoffelLang compiler generates optimized VM bytecode
  4. Testing: Local VM execution for development and testing
  5. Deployment: MPC network deployment with protocol integration

Runtime Execution

  1. Program Loading: StoffelVM loads compiled bytecode
  2. Secret Sharing: Input data is secret-shared across MPC nodes
  3. Secure Computation: VM executes with MPC protocol integration
  4. Result Reconstruction: Output is reconstructed from secret shares

Data Flow

Clear Data Path

  • Public inputs and configuration data
  • Direct VM register operations
  • No cryptographic overhead
  • Immediate availability across all nodes

Secret Data Path

  • Private inputs requiring protection
  • Automatic secret sharing on input
  • MPC protocol operations during computation
  • Selective reveal for output reconstruction

Security Architecture

Isolation Boundaries

  • Process Isolation: Each MPC node runs in isolated environment
  • Memory Protection: Clear and secret data separation
  • Network Security: Encrypted communication between nodes
  • Access Control: Role-based access to computation resources

Trust Model

  • Honest Majority: Assumes majority of nodes are honest
  • Semi-Honest Adversary: Protects against passive attacks
  • Input Privacy: Individual inputs remain private
  • Computation Privacy: Intermediate values are protected

Scalability Design

Horizontal Scaling

  • Node Addition: Dynamic addition of MPC nodes
  • Load Distribution: Computation workload balancing
  • Geographic Distribution: Global node deployment support

Vertical Scaling

  • Resource Optimization: Efficient CPU and memory usage
  • Parallel Execution: Multi-threaded computation where possible
  • Caching Strategies: Optimized data and computation caching

Integration Points

External Systems

  • Database Integration: Secure querying of external databases
  • API Integration: RESTful APIs for system interaction
  • Blockchain Integration: Smart contract integration for verification

Development Tools

  • IDE Support: Language server protocol integration
  • Debugging Tools: Comprehensive debugging and profiling
  • Testing Frameworks: Specialized testing for MPC applications

This architecture enables secure, scalable, and developer-friendly multi-party computation while maintaining strong security guarantees.

Design Rationale

Protocol Agnostic Design

The virtual machine is designed to be protocol-agnostic for several reasons:

  1. Flexibility

    • Support for different MPC protocols without architectural changes
    • Easy integration of new protocols as they are developed
    • Ability to switch protocols based on specific requirements
  2. Future-Proofing

    • Not tied to limitations of specific protocols
    • Can adapt to advances in MPC research
    • Supports hybrid protocol approaches

Extensibility

The architecture emphasizes extensibility through:

  1. Modular Design

    • Clear separation of concerns
    • Plugin system for new instructions
    • Customizable optimization passes
  2. Abstract Interfaces

    • Protocol-independent instruction definitions
    • Flexible memory model
    • Extensible register system

Architecture

Stoffel VM is a register based virtual machine with two sets of registers. Clear registers for manipulating non-secret values. Secret registers are used for manipulating secret values.

Technical Overview

Virtual Machine Architecture

  • What type of VM is stoffel
  • Clear vs Secret values

Instruction Set

  • Complete reference of supported VM instructions
  • Opcode specifications and behavior
  • Optimization opportunities

Builtin Types

  • Overview of core data types (numbers, strings, arrays, etc.)
  • Type conversion and manipulation
  • Memory representation and optimization

Activation Records

  • Call stack management and function invocation
  • Local variable scoping and lifetime
  • Optimizing stack frame allocation

VM Functions

  • Virtual machine architecture overview
  • Execution model and stack management
  • Error handling

Closures Overview

  • Lexical scoping and variable capture
  • Implementation details and memory management

Foreign Function Interface

  • Integrating with external libraries and systems
  • Data marshalling and type conversion
  • Performance considerations for FFI calls

Builtin Methods

  • Standard library functions and utilities
  • Common operations for each data type

Runtime Hooks

  • Extension points for monitoring and customization
  • Performance profiling and instrumentation
  • Debugging facilities

Why a Register Machine?

The choice of a register-based architecture over a stack-based design was driven by several key factors:

  1. Parallelization Opportunities

    • Register machines allow for easier identification of independent instructions
    • Multiple instructions can be executed in parallel, reducing overall execution time
    • Better suited for modern hardware architectures
  2. Communication Efficiency

    • Reduced number of memory access operations
    • Fewer rounds of communication in Multi-Party Computation (MPC) contexts
    • More efficient instruction encoding
  3. Optimization Potential

    • Direct access to operands enables better optimization strategies
    • Easier to implement specialized instructions
    • More straightforward analysis of data flow

Why dedicated clear and secret registers

  1. Implicit reveal and hide
    • Having dedicated registers for secret and clear values allows us to implicitly reveal and hide values as they're moved between registers.
    • Separation of registers allows for optimizations to be applied specifically to clear or secret operations.
    • Avoids having to track the type of the virtual register during runtime as values may become secret shared or reveal through the course of execution.

VM Architecture Details

This section covers the detailed architectural design of StoffelVM. For implementation details and current status, see StoffelVM Implementation Details.

Register Architecture

StoffelVM uses a register-based architecture with two distinct register spaces:

Clear Registers

  • Store public/non-secret values
  • Direct CPU register mapping for performance
  • Standard arithmetic and logical operations
  • No cryptographic overhead

Secret Registers

  • Store secret-shared values for MPC
  • Protocol-agnostic secret handling
  • Automatic secret sharing and reconstruction
  • MPC-optimized operations

Memory Model

Object Store

  • Dynamic object allocation with reference counting
  • Key-value mappings for flexible data structures
  • Garbage collection integration points

Array Store

  • Contiguous memory layout for arrays
  • Dynamic resizing capabilities
  • Index bounds checking

Stack Management

  • Function call activation records
  • Parameter passing via argument stack
  • Local variable storage

Instruction Pipeline

Fetch-Decode-Execute Cycle

  1. Instruction Fetch: Retrieve next instruction from program counter
  2. Decode: Parse instruction opcode and operands
  3. Execute: Perform operation with register/memory access
  4. Writeback: Store result in destination register

Hook Integration Points

  • Pre-instruction hooks for debugging
  • Post-instruction hooks for monitoring
  • Register access hooks for MPC protocol integration
  • Memory operation hooks for garbage collection

Type System Integration

Value Types

The VM supports a rich type system with runtime type information:

  • Primitive types (integers, floats, booleans, strings)
  • Complex types (objects, arrays, closures)
  • Foreign objects for host language integration

Type Safety

  • Runtime type checking for operations
  • Type coercion rules for mixed operations
  • Error handling for type mismatches

Closure System

Lexical Scoping

  • True lexical scoping with upvalue capture
  • Closure creation with environment capture
  • Upvalue sharing between closures

Function Calls

  • Dynamic function dispatch
  • Parameter binding and local variable allocation
  • Return value handling

Protocol Integration

MPC Protocol Interface

  • Abstract protocol operations for secret sharing
  • Reveal operations for secret-to-clear transitions
  • Communication round optimization

Clear/Secret Transitions

  • Automatic hiding (clear → secret) on register moves
  • Explicit revealing (secret → clear) operations
  • Type preservation during transitions

This architectural design enables efficient MPC computation while maintaining the flexibility to support different protocols and optimization strategies.

MPC Integration

This section covers how the Stoffel ecosystem integrates with Multi-Party Computation protocols.

Protocol Architecture

Stoffel is designed to be protocol-agnostic, allowing integration with different MPC protocols while maintaining a consistent interface.

Current Protocol Support

  • HoneyBadger MPC: Primary protocol implementation in Rust
  • Configurable Security: Adjustable threshold parameters
  • Multiple Fields: Support for BLS12-381, BN254, and other cryptographic fields

Integration Points

StoffelVM Integration

  • Secret register operations map to MPC protocol primitives
  • Automatic secret sharing for values moved to secret registers
  • Reveal operations for transitioning from secret to clear

Network Communication

  • Direct node communication for MPC operations
  • Optional coordinator for metadata exchange
  • Efficient batching of operations for reduced communication rounds

Python SDK Integration

  • High-level API abstracts protocol complexity
  • Clear separation between secret and public inputs
  • Automatic result reconstruction from secret shares

Security Model

Threat Model

  • Assumes honest majority with up to (n-1)/3 corrupted parties
  • Protects against semi-honest adversaries
  • Configurable security parameters for different scenarios

Data Protection

  • Input privacy through secret sharing
  • Computation privacy through secure protocols
  • Output privacy with selective reveal operations

Performance Considerations

Communication Optimization

  • Batched operations to reduce round complexity
  • Efficient serialization of protocol messages
  • Network topology optimization for latency

Computational Efficiency

  • Native field arithmetic operations
  • Optimized secret sharing algorithms
  • Parallel computation where possible

This integration enables secure multi-party computation while maintaining developer-friendly abstractions.

Sources

This is a comprehensive list of resources or referenced when designing and making Stoffel.

This work was created through a mix of independent research and development plus outside sources listed below, though as Newton once said, 'If I have seen further, it is by standing on the shoulders of giants.' Any similarities to existing works not listed are purely coincidental and a testament to the universal nature of good ideas.

Incomplete List Disclaimer

This list of sources attempts to be as complete as possible. Some sources may have been forgotten or haven't found their way into the list yet!

Contributing

Building from Source

Testing