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, test, and run 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 execution

Core Commands

Project Management

# Initialize new projects
stoffel init my-project                    # Default StoffelLang project
stoffel init my-project --template python  # Python SDK integration
stoffel init my-project --template rust    # Rust SDK integration
stoffel init my-project --lib              # Create a library project
stoffel init my-project --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 (.stfb)
stoffel compile -O3                        # Maximum optimization (levels 0-3)
stoffel compile --disassemble program.stfb # Disassemble bytecode
stoffel compile --print-ir                 # Print intermediate representation

Building

# Build entire project
stoffel build                              # Debug build
stoffel build --release                    # Release build with optimizations
stoffel build -O2                          # Specific optimization level

Development

# Compile and run locally
stoffel dev                                # Default: 5 parties
stoffel dev --parties 7                    # Custom party count
stoffel dev --field bn254                  # Different cryptographic field

Execution

# Run compiled bytecode
stoffel run                                # Auto-discover in target/
stoffel run program.stfb                   # Run specific file
stoffel run --entry my_function            # Custom entry point

Testing

# Run project tests
stoffel test                               # Discover and run all tests
stoffel test --test specific_test          # Run specific test function
stoffel test --integration                 # Integration tests only
stoffel test --verbose                     # Detailed output

Available Templates

The CLI provides templates for different development scenarios:

Language-Specific Templates

TemplateDescriptionStatus
stoffelPure StoffelLang project (default)✅ Complete
pythonPython SDK integration with Poetry✅ Complete
rustRust SDK integration✅ Complete
typescriptTypeScript/Node.js integration⚠️ Skeleton (SDK pending)
solidity-foundrySolidity with Foundry framework✅ Complete
solidity-hardhatSolidity with Hardhat framework✅ Complete

Template Usage

stoffel init my-app                           # Default stoffel template
stoffel init my-app --template python         # Python project
stoffel init my-app --template rust           # Rust project
stoffel init my-app --template solidity-foundry  # Foundry project
stoffel init my-app --template solidity-hardhat  # Hardhat project

Project Structure

Pure StoffelLang Project

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

Python Template Structure

my-python-project/
├── pyproject.toml           # Poetry configuration
├── src/
│   └── my_python_project/
│       └── main.py         # Python entry point
├── stoffel/                 # Nested Stoffel project
│   ├── Stoffel.toml
│   └── src/
│       └── program.stfl    # StoffelLang program
├── tests/
│   └── test_main.py        # Python tests
└── README.md

Rust Template Structure

my-rust-project/
├── Cargo.toml               # Rust project config
├── src/
│   └── main.rs             # Rust entry point with SDK
├── stoffel/                 # Nested Stoffel project
│   ├── Stoffel.toml
│   └── src/
│       └── program.stfl    # StoffelLang program
└── README.md

Solidity Template Structure (Foundry)

my-solidity-project/
├── foundry.toml             # Foundry configuration
├── src/
│   └── MyMPCApp.sol        # Main contract
├── test/
│   └── MyMPCApp.t.sol      # Foundry tests
├── script/
│   └── Deploy.s.sol        # Deployment script
├── stoffel/                 # Nested Stoffel project
│   ├── Stoffel.toml
│   └── src/
│       └── program.stfl
└── 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>"]

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

[build]
optimization_level = 2
output_dir = "target"

MPC Configuration

The CLI supports configurable MPC parameters:

  • Parties: Number of parties in the MPC computation (minimum 4 for HoneyBadger)
  • Threshold: Maximum number of corrupted parties tolerated
  • Constraint: parties >= 3 * threshold + 1
  • Cryptographic Fields: BLS12-381 (default), BN254, Secp256k1, Prime61

Valid Configurations

PartiesThresholdValid?
41✅ (4 >= 4)
51✅ (5 >= 4) - default
72✅ (7 >= 7)
31❌ (3 < 4)

Help System

The CLI provides comprehensive help for all commands:

stoffel --help                    # Main help
stoffel init --help               # Command-specific help
stoffel compile --help            # Compilation options
stoffel test --help               # Testing options

Command Status

Implemented Commands

CommandDescription
initProject initialization with templates
compileStoffelLang compilation
buildBuild entire project
devDevelopment mode (compile + run)
runExecute compiled bytecode
testTest discovery and execution

Planned Commands

CommandDescription
deployDeployment to MPC networks
addPackage dependency management
updateUpdate dependencies
publishPublish packages to registry
cleanRemove build artifacts

Examples

Quick Start

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

Rust SDK Integration

# Create Rust project with SDK
stoffel init secure-compute --template rust
cd secure-compute
cargo build
cargo run

Solidity Integration

# Create Solidity project with Foundry
stoffel init my-contract --template solidity-foundry
cd my-contract
forge build
forge test

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
var 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
var my_variable = 10
var _private_value = "secret"
var camelCase = true
var snake_case_name = "Alice"

Reserved keywords:

var def type object enum main
if else elif while for in
return break continue
true false nil secret discard

Variables and Types

Variable Declarations

StoffelLang uses var for variable declarations:

# Variable with type inference
var name = "Alice"
var age = 25
var is_active = true

# Variable with explicit type annotation
var counter: int64 = 0
var status: string = "pending"

# Variable declaration without initialization (requires type)
var result: int64

Type Annotations

Explicit type annotations use colon syntax:

var count: int64 = 100
var message: string = "Hello"
var flag: bool = false

Type Inference

StoffelLang can infer types from context:

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

Primitive Types

Integer Types

StoffelLang supports multiple integer types:

# Signed integers
var a: int64 = 100
var b: int32 = 50
var c: int16 = 25
var d: int8 = 10

# Unsigned integers
var e: uint64 = 100
var f: uint32 = 50
var g: uint16 = 25
var h: uint8 = 10

# Typed integer literals
var typed_i64 = 42i64
var typed_u32 = 100u32
var typed_i8 = 127i8

Boolean Type

var is_ready: bool = true
var is_complete: bool = false

String Type

var greeting: string = "Hello, world!"
var empty_string: string = ""

Nil Type

var nothing = nil

Secret Types

The secret keyword creates MPC-aware types for secure computation:

# Secret variable declaration
secret var my_secret = 42

# Secret with explicit type
var secret_value: secret int64 = 100

# Secret function parameter
def process_secret(data: secret int64) -> secret int64:
    return data * 2

Important Constraints:

  • Secret values cannot be used in if or while conditions
  • Comparisons involving secrets produce secret boolean results
  • Use ClientStore.take_share() to get secret inputs from MPC clients

Functions

Function Definitions

Functions use the def keyword:

# Basic function
def greet(name: string) -> string:
    return "Hello, " + name

# Function with multiple parameters
def add(a: int64, b: int64) -> int64:
    return a + b

# Function without return value
def log_message(msg: string) -> nil:
    print(msg)

# Function with secret parameters
def secure_multiply(a: secret int64, b: secret int64) -> secret int64:
    return a * b

Entry Point

The program entry point uses the main keyword:

main main() -> int64:
    return 42

Function Calls

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

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

Functions with Local Variables

def calculate_area(length: int64, width: int64) -> int64:
    var area = length * width
    print("Area calculated")
    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")

While Loops

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

For Loops

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

Loop Control

# Break and continue
var i = 0
while i < 100:
    i = i + 1
    if i == 5:
        continue
    if i == 10:
        break

Operators

Arithmetic Operators

var a = 10
var b = 3

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

Comparison Operators

var x = 10
var y = 20

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

Bitwise Operators

var a = 5   # 0101 in binary
var b = 3   # 0011 in binary

var and_result = a & b    # 1 (0001)
var or_result = a | b     # 7 (0111)
var xor_result = a ^ b    # 6 (0110)
var not_result = ~a       # bitwise NOT
var shift_left = a << 1   # 10
var shift_right = a >> 1  # 2

Built-in Functions

print

Output text to the console:

def greet() -> nil:
    print("Hello, World!")

ClientStore

Access secret inputs from MPC clients:

# Get the number of connected clients
var num_clients = ClientStore.get_number_clients()

# Take a secret share from a client
# Must be assigned to a secret variable!
secret var client_input = ClientStore.take_share(0, 0)

# Parameters: (party_id, share_index)
secret var share1 = ClientStore.take_share(0, 0)  # Party 0, share 0
secret var share2 = ClientStore.take_share(1, 0)  # Party 1, share 0

Important: Results from ClientStore.take_share() must be assigned to secret variables.

Working with Secret Types

Secret Arithmetic

def secure_calculation(a: secret int64, b: secret int64) -> secret int64:
    var result = a + b
    return result * 2

def mixed_operation(secret_val: secret int64, public_val: int64) -> secret int64:
    # Public values can be used with secrets
    return secret_val * public_val

MPC Input Pattern

Common pattern for processing client inputs:

def process_client_inputs() -> secret int64:
    # Get inputs from two clients
    secret var input1 = ClientStore.take_share(0, 0)
    secret var input2 = ClientStore.take_share(1, 0)

    # Perform secure computation
    return input1 + input2

main main() -> nil:
    var num_clients = ClientStore.get_number_clients()
    secret var result = process_client_inputs()
    print("Computation complete")

Complete Examples

Fibonacci (Iterative)

def fibonacci(n: int64) -> int64:
    if n <= 1:
        return n
    var a: int64 = 0
    var b: int64 = 1
    for i in 2..n:
        var temp = a + b
        a = b
        b = temp
    return b

main main() -> int64:
    return fibonacci(10)

Factorial (Recursive)

def factorial(n: int64) -> int64:
    if n <= 1:
        return 1
    return n * factorial(n - 1)

main main() -> int64:
    return factorial(5)  # Returns 120

Secure Sum

def secure_sum() -> secret int64:
    var num_clients = ClientStore.get_number_clients()
    secret var total: secret int64 = ClientStore.take_share(0, 0)

    # Note: In practice, you'd loop based on num_clients
    secret var input2 = ClientStore.take_share(1, 0)
    total = total + input2

    return total

main main() -> nil:
    secret var result = secure_sum()
    print("Sum computed")

Data Structures (Planned)

Object Types

Note: Object types are parsed but have limited code generation support.

# Object type definition (planned)
type Person = object
    name: string
    age: int64

Enum Types

Note: Enum types are parsed but have limited code generation support.

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

Best Practices

Naming Conventions

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

def calculate_total_cost(base_price: int64, tax_rate: int64) -> int64:
    return base_price + (base_price * tax_rate / 100)

# Use PascalCase for types (when supported)
type UserAccount = object
    user_id: int64

Secret Type Usage

# Clearly distinguish between public and secret data
def process_transaction(
    public_user_id: int64,
    secret_amount: secret int64
) -> secret int64:
    # Perform secure computation
    return secret_amount * 2

# Avoid using secrets in conditions (not allowed!)
# BAD: if secret_value > 0:  # This will fail!
# GOOD: Keep secret values in computations only

This syntax guide covers the current StoffelLang implementation. Features marked as "planned" are parsed by the compiler but may have limited code generation support.

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

StoffelVM is a register-based virtual machine optimized for Multi-Party Computation. This page documents the complete instruction set and type system.

Architecture Overview

  • Register-based: Operations use numbered registers rather than a stack
  • Dual register sets: Separate registers for clear (public) and secret values
  • 32 registers: Registers 0-15 for clear values, 16-31 for secret values
  • Compare flag: Single flag for conditional jumps

Value Types

Primitive Types

TypeDescriptionSize
I64Signed 64-bit integer8 bytes
I32Signed 32-bit integer4 bytes
I16Signed 16-bit integer2 bytes
I8Signed 8-bit integer1 byte
U64Unsigned 64-bit integer8 bytes
U32Unsigned 32-bit integer4 bytes
U16Unsigned 16-bit integer2 bytes
U8Unsigned 8-bit integer1 byte
FloatFixed-point number (stored as I64)8 bytes
BoolBoolean value1 byte
StringUTF-8 stringVariable
UnitNil/void value0 bytes

Complex Types

TypeDescription
ObjectKey-value map (reference)
ArrayIndexed collection (reference)
ClosureFunction with captured environment
ForeignRust object exposed via FFI
ShareSecret-shared value for MPC

Share Types (MPC)

Secret-shared values carry a type tag:

ShareType:
  Int(i64), I32, I16, I8
  U8, U16, U32, U64
  Float, Bool

Instruction Set

Memory Operations

LD - Load from Stack

Load a value from the stack into a register.

LD dest_reg, stack_offset
  • dest_reg: Target register (0-31)
  • stack_offset: Offset from stack base

LDI - Load Immediate

Load a constant value into a register.

LDI dest_reg, constant_index
  • dest_reg: Target register (0-31)
  • constant_index: Index into constant pool

MOV - Move

Copy value from one register to another.

MOV dest_reg, src_reg
  • dest_reg: Target register (0-31)
  • src_reg: Source register (0-31)

PUSHARG - Push Argument

Push a register value onto the argument stack for function calls.

PUSHARG src_reg
  • src_reg: Register containing the argument

Arithmetic Operations

All arithmetic operations follow the pattern:

OP dest_reg, src1_reg, src2_reg
InstructionOperationDescription
ADDdest = src1 + src2Addition
SUBdest = src1 - src2Subtraction
MULdest = src1 * src2Multiplication
DIVdest = src1 / src2Integer division
MODdest = src1 % src2Modulo

Example:

LDI R0, 10      # R0 = 10
LDI R1, 3       # R1 = 3
ADD R2, R0, R1  # R2 = 13
SUB R3, R0, R1  # R3 = 7
MUL R4, R0, R1  # R4 = 30
DIV R5, R0, R1  # R5 = 3
MOD R6, R0, R1  # R6 = 1

Bitwise Operations

InstructionOperationDescription
ANDdest = src1 & src2Bitwise AND
ORdest = src1 \| src2Bitwise OR
XORdest = src1 ^ src2Bitwise XOR
NOTdest = ~srcBitwise NOT (unary)
SHLdest = src << amountShift left
SHRdest = src >> amountShift right

Note: NOT only takes two operands: NOT dest_reg, src_reg

Example:

LDI R0, 5       # R0 = 0101 (binary)
LDI R1, 3       # R1 = 0011 (binary)
AND R2, R0, R1  # R2 = 0001 = 1
OR  R3, R0, R1  # R3 = 0111 = 7
XOR R4, R0, R1  # R4 = 0110 = 6
NOT R5, R0      # R5 = ~5
LDI R6, 1
SHL R7, R0, R6  # R7 = 10
SHR R8, R0, R6  # R8 = 2

Comparison Operation

CMP - Compare

Compare two registers and set the compare flag.

CMP reg1, reg2

Sets compare flag:

  • -1 if reg1 < reg2
  • 0 if reg1 == reg2
  • 1 if reg1 > reg2

Control Flow

JMP - Unconditional Jump

Jump to a labeled instruction.

JMP label

Conditional Jumps

Jump based on the compare flag (set by CMP):

InstructionConditionDescription
JMPEQflag == 0Jump if equal
JMPNEQflag != 0Jump if not equal
JMPLTflag == -1Jump if less than
JMPGTflag == 1Jump if greater than

Example:

LDI R0, 10
LDI R1, 20
CMP R0, R1      # flag = -1 (10 < 20)
JMPLT less      # Jumps because flag == -1
JMP end

less:
  LDI R2, 1     # This executes
  JMP end

end:
  RET R2

Function Operations

CALL - Call Function

Call a function by name or index.

CALL function_name
  • Arguments must be pushed with PUSHARG before calling
  • Creates new activation record
  • Jumps to function entry point

RET - Return

Return from function with a value.

RET src_reg
  • src_reg: Register containing return value
  • Pops activation record
  • Returns control to caller

Example:

# Function: add(a, b) -> a + b
add:
  LD R0, 0        # Load first argument
  LD R1, 1        # Load second argument
  ADD R2, R0, R1  # Add them
  RET R2          # Return result

# Calling code:
main:
  LDI R0, 10
  PUSHARG R0      # Push first argument
  LDI R1, 20
  PUSHARG R1      # Push second argument
  CALL add        # Call function
  # Result is now in return register

Opcode Encoding

Instructions are encoded as bytes with the following opcodes:

OpcodeHexInstruction
00x00LD
10x01LDI
20x02MOV
30x03ADD
40x04SUB
50x05MUL
60x06DIV
70x07MOD
80x08AND
90x09OR
100x0AXOR
110x0BNOT
120x0CSHL
130x0DSHR
140x0EJMP
150x0FJMPEQ
160x10JMPNEQ
170x11CALL
180x12RET
190x13PUSHARG
200x14CMP
210x15JMPLT
220x16JMPGT

Bytecode Format

Compiled programs use the .stfb or .stfbin extension:

Header:
  [4 bytes] Magic: "STFL"
  [2 bytes] Version: 1

Constants:
  [4 bytes] Count
  [variable] Constant values (type + data)

Functions:
  [4 bytes] Count
  For each function:
    [variable] Name (length-prefixed string)
    [4 bytes] Register count
    [4 bytes] Parameter count
    [variable] Parameter names
    [4 bytes] Upvalue count
    [variable] Upvalue names
    [variable] Parent function name (optional)
    [4 bytes] Label count
    [variable] Labels (name + instruction index)
    [4 bytes] Instruction count
    [variable] Instructions

Execution Model

Activation Records

Each function call creates an activation record containing:

  • Function name
  • Local variables (HashMap)
  • Registers (SmallVec, optimized for 16)
  • Instructions
  • Upvalues (for closures)
  • Argument stack
  • Compare flag
  • Instruction pointer

Register Allocation

  • Registers 0-15: Clear (public) values
  • Registers 16-31: Secret (MPC) values
  • Compiler performs graph-coloring register allocation
  • Spills to stack when registers exhausted

Constant Pool

Constants are stored in a separate pool and referenced by index:

  • Reduces instruction size
  • Enables deduplication
  • Supports all value types

MPC Integration

For MPC operations, the VM integrates with the HoneyBadger protocol:

Secret Operations

When operating on Share values:

  • Arithmetic uses secure MPC protocols
  • multiply_share() uses Beaver triples
  • open_share() reconstructs values

Client Input

The ClientStore provides access to client inputs:

  • take_share(party_id, index) retrieves secret shares
  • get_number_clients() returns participant count

Next Steps

Using the VM

Built-in Functions

Rust SDK Overview

The Stoffel Rust SDK provides a high-level API for building Multi-Party Computation (MPC) applications in Rust. It bridges the StoffelLang compiler, StoffelVM execution engine, and HoneyBadger MPC protocol into a cohesive, developer-friendly interface.

Design Philosophy

The SDK is built around three core principles:

Progressive Disclosure

Three API levels for different needs:

  • Simple API: Quick compilation and local testing
  • Builder Pattern: Full MPC configuration
  • Advanced API: Direct access to network and protocol layers

MPC-First Design

Programs are configured for MPC during compilation, ensuring all participants use consistent parameters.

Clean Abstractions

The SDK hides cryptographic complexity while providing clear semantics for secret and public data.

Quick Start

Simple Local Execution

use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let source = r#"
        def add(a: int64, b: int64) -> int64:
            return a + b

        main main() -> int64:
            return add(10, 20)
    "#;

    let result = Stoffel::compile(source)?
        .execute_local()?;

    println!("Result: {:?}", result);
    Ok(())
}

MPC Configuration

use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let runtime = Stoffel::compile(source)?
        .parties(5)           // 5-party MPC network
        .threshold(1)         // Byzantine fault tolerance
        .instance_id(42)      // Unique computation ID
        .build()?;

    // Test locally before deployment
    let result = runtime.program().execute_local()?;
    println!("Local test result: {:?}", result);

    Ok(())
}

Creating MPC Participants

#![allow(unused)]
fn main() {
use stoffel_rust_sdk::prelude::*;

async fn setup_mpc() -> Result<()> {
    let runtime = Stoffel::compile(source)?
        .parties(5)
        .threshold(1)
        .build()?;

    // Create an MPC server (compute node)
    let server = runtime.server(0)
        .with_preprocessing(10, 25)  // 10 triples, 25 random shares
        .build()?;

    // Create an MPC client (input provider)
    let client = runtime.client(100)
        .with_inputs(vec![10, 20])
        .build()?;

    Ok(())
}
}

Core Components

Stoffel Builder

The entry point for all SDK operations:

#![allow(unused)]
fn main() {
Stoffel::compile(source)      // Compile from string
Stoffel::compile_file(path)   // Compile from file
Stoffel::load(bytecode)       // Load pre-compiled bytecode
}

StoffelRuntime

After building, provides access to:

#![allow(unused)]
fn main() {
let runtime = Stoffel::compile(source)?.build()?;

runtime.program()      // Access compiled bytecode
runtime.client(id)     // Create MPC client builder
runtime.server(id)     // Create MPC server builder
runtime.node(id)       // Create MPC node builder (client + server)
}

Program

Pure bytecode container with execution methods:

#![allow(unused)]
fn main() {
let program = runtime.program();

program.execute_local()?;                    // Run main function
program.execute_local_function("func")?;     // Run specific function
program.list_functions()?;                   // List available functions
program.save("output.stfb")?;                // Save bytecode to file
}

MPC Participants

Three participant types for different roles:

TypeProvides InputsComputesReceives Outputs
MPCClient
MPCServer
MPCNode

MPC Configuration

Protocol Parameters

#![allow(unused)]
fn main() {
Stoffel::compile(source)?
    .parties(5)                          // Number of parties (min: 4)
    .threshold(1)                        // Fault tolerance
    .instance_id(42)                     // Computation instance
    .protocol(ProtocolType::HoneyBadger) // MPC protocol
    .share_type(ShareType::Robust)       // Secret sharing scheme
    .build()?
}

Validation Rules

The SDK automatically validates MPC parameters:

  • HoneyBadger: Requires n >= 3t + 1 where n = parties, t = threshold
  • Minimum 4 parties with threshold 1
  • Common configurations:
    • 4 parties, threshold 1: 4 >= 4
    • 5 parties, threshold 1: 5 >= 4 ✓ (recommended default)
    • 7 parties, threshold 2: 7 >= 7

Error Handling

The SDK provides comprehensive error types:

#![allow(unused)]
fn main() {
use stoffel_rust_sdk::error::{Error, Result};

match Stoffel::compile(source)?.build() {
    Ok(runtime) => { /* success */ }
    Err(Error::CompilationError(msg)) => { /* syntax error */ }
    Err(Error::Configuration(msg)) => { /* invalid MPC params */ }
    Err(Error::Network(msg)) => { /* connection error */ }
    Err(e) => { /* other error */ }
}
}

Error categories:

  • CompilationError: StoffelLang syntax or semantic errors
  • RuntimeError: VM execution failures
  • MPCError: Protocol-level errors
  • Configuration: Invalid parameters
  • Network: Connection failures
  • IoError: File operations

Network Configuration

Programmatic Configuration

#![allow(unused)]
fn main() {
let runtime = Stoffel::compile(source)?
    .parties(5)
    .threshold(1)
    .build()?;

let server = runtime.server(0).build()?;
server.add_peer(1, "127.0.0.1:19201".parse()?);
server.bind_and_listen("127.0.0.1:19200".parse()?).await?;
}

TOML Configuration

# stoffel.toml
[network]
party_id = 0
bind_address = "127.0.0.1:9001"
bootstrap_address = "127.0.0.1:9000"
min_parties = 4

[mpc]
n_parties = 5
threshold = 1
instance_id = 12345
#![allow(unused)]
fn main() {
let runtime = Stoffel::compile(source)?
    .network_config_file("stoffel.toml")?
    .build()?;
}

Next Steps

Installation

Prerequisites

  • Rust 1.70 or higher
  • Git (for submodule dependencies)
  • Stoffel CLI (optional, for project scaffolding)

Installation Methods

Add to your Cargo.toml:

[dependencies]
stoffel-rust-sdk = { git = "https://github.com/Stoffel-Labs/stoffel-rust-sdk" }

Then run:

cargo build

Using Stoffel CLI Template

The easiest way to start a new Rust MPC project:

# Install Stoffel CLI first (see Getting Started)
stoffel init my-mpc-app --template rust
cd my-mpc-app
cargo build

This creates a complete project with:

  • Rust application with SDK integration
  • StoffelLang program in stoffel/src/program.stfl
  • Example code demonstrating the SDK API
  • Ready-to-run configuration

From Source

For development or customization:

git clone https://github.com/Stoffel-Labs/stoffel-rust-sdk.git
cd stoffel-rust-sdk

# Initialize submodules (required)
git submodule update --init --recursive

cargo build
cargo test

Verifying Installation

Create a simple test program:

use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let source = r#"
        main main() -> int64:
            return 42
    "#;

    let result = Stoffel::compile(source)?
        .execute_local()?;

    println!("Result: {:?}", result);
    Ok(())
}

Run it:

cargo run

Expected output:

Result: I64(42)

Dependencies

The SDK depends on several Stoffel components (managed as git submodules):

ComponentPurpose
stoffellangStoffelLang compiler
stoffel-vmVirtual machine runtime
stoffelmpc-mpcHoneyBadger MPC protocol
stoffelnetQUIC networking

These are automatically fetched when you add the SDK as a dependency.

Platform Support

PlatformStatus
Linux (x86_64)✅ Fully supported
macOS (x86_64, ARM64)✅ Fully supported
Windows (WSL2)✅ Supported
Windows (native)⚠️ Experimental

Troubleshooting

Submodule Issues

If you see errors about missing dependencies:

git submodule update --init --recursive

Build Failures

Ensure you have the latest Rust:

rustup update stable

Linking Errors

On Linux, you may need:

sudo apt-get install build-essential pkg-config libssl-dev

On macOS:

xcode-select --install

Next Steps

API Reference

Stoffel Builder

The main entry point for all SDK operations.

Compilation Methods

#![allow(unused)]
fn main() {
// Compile from source string
Stoffel::compile(source: &str) -> Result<StoffelBuilder>

// Compile from file
Stoffel::compile_file(path: &str) -> Result<StoffelBuilder>

// Load pre-compiled bytecode
Stoffel::load(bytecode: Vec<u8>) -> Result<StoffelBuilder>
}

Configuration Methods

#![allow(unused)]
fn main() {
impl StoffelBuilder {
    // MPC party count (minimum 4 for HoneyBadger)
    fn parties(self, n: usize) -> Self

    // Fault tolerance threshold (default: 1)
    fn threshold(self, t: usize) -> Self

    // Unique computation instance ID
    fn instance_id(self, id: u64) -> Self

    // MPC protocol selection
    fn protocol(self, protocol: ProtocolType) -> Self

    // Secret sharing scheme
    fn share_type(self, share_type: ShareType) -> Self

    // Enable compiler optimization
    fn optimize(self, enabled: bool) -> Self

    // Load network config from TOML file
    fn network_config_file(self, path: &str) -> Result<Self>

    // Set network config programmatically
    fn network_config(self, config: NetworkConfig) -> Self

    // Build the runtime
    fn build(self) -> Result<StoffelRuntime>

    // Quick local execution (skips MPC setup)
    fn execute_local(self) -> Result<Value>
}
}

Types

#![allow(unused)]
fn main() {
pub enum ProtocolType {
    HoneyBadger,  // Currently the only supported protocol
}

pub enum ShareType {
    Robust,      // Reed-Solomon error correction (default)
    NonRobust,   // Standard Shamir secret sharing
}
}

StoffelRuntime

Created by StoffelBuilder::build(), provides access to program and MPC participants.

#![allow(unused)]
fn main() {
impl StoffelRuntime {
    // Access the compiled program
    fn program(&self) -> &Program

    // Get MPC configuration
    fn mpc_config(&self) -> Option<(usize, usize, u64)>  // (parties, threshold, instance_id)

    // Get protocol type
    fn protocol_type(&self) -> ProtocolType

    // Get share type
    fn share_type(&self) -> ShareType

    // Create MPC client builder
    fn client(&self, id: u64) -> MPCClientBuilder

    // Create MPC server builder
    fn server(&self, id: usize) -> MPCServerBuilder

    // Create MPC node builder (combined client + server)
    fn node(&self, id: usize) -> MPCNodeBuilder
}
}

Program

Pure bytecode container with execution methods.

#![allow(unused)]
fn main() {
impl Program {
    // Get raw bytecode
    fn bytecode(&self) -> &[u8]

    // Save bytecode to file
    fn save(&self, path: &str) -> Result<()>

    // Execute main function locally (no MPC)
    fn execute_local(&self) -> Result<Value>

    // Execute specific function locally
    fn execute_local_function(&self, name: &str) -> Result<Value>

    // Execute function with arguments
    fn execute_local_with_args(&self, name: &str, args: Vec<Value>) -> Result<Value>

    // List available functions
    fn list_functions(&self) -> Result<Vec<FunctionInfo>>
}

pub struct FunctionInfo {
    pub name: String,
    pub parameters: Vec<String>,
    pub register_count: usize,
}
}

MPCClient

Input provider that does not participate in computation.

Builder

#![allow(unused)]
fn main() {
impl MPCClientBuilder {
    // Set secret inputs
    fn with_inputs(self, inputs: Vec<i64>) -> Self

    // Build the client
    fn build(self) -> Result<MPCClient>
}
}

Methods

#![allow(unused)]
fn main() {
impl MPCClient {
    // Add server to connect to
    fn add_server(&mut self, id: usize, addr: SocketAddr)

    // Connect to all configured servers
    async fn connect_to_servers(&mut self) -> Result<()>

    // Send secret-shared inputs to servers
    async fn send_inputs(&mut self) -> Result<()>

    // Receive and reconstruct outputs
    async fn receive_outputs(&mut self) -> Result<Value>
}
}

MPCServer

Compute node that performs MPC operations.

Builder

#![allow(unused)]
fn main() {
impl MPCServerBuilder {
    // Configure preprocessing material
    fn with_preprocessing(self, triples: usize, random_shares: usize) -> Self

    // Build the server
    fn build(self) -> Result<MPCServer>
}
}

Methods

#![allow(unused)]
fn main() {
impl MPCServer {
    // Add peer server
    fn add_peer(&mut self, id: usize, addr: SocketAddr)

    // Start listening for connections
    async fn bind_and_listen(&mut self, addr: SocketAddr) -> Result<()>

    // Initialize the MPC node
    fn initialize_node(&mut self) -> Result<()>

    // Spawn message processor
    async fn spawn_message_processor(&mut self, receiver: Receiver<Message>, id: usize) -> Result<()>

    // Connect to peer servers
    async fn connect_to_peers(&mut self) -> Result<()>

    // Load program bytecode
    fn load_bytecode(&mut self, bytecode: &[u8]) -> Result<()>
}
}

MPCNode

Combined client and server for peer-to-peer MPC.

Builder

#![allow(unused)]
fn main() {
impl MPCNodeBuilder {
    // Set secret inputs
    fn with_inputs(self, inputs: Vec<i64>) -> Self

    // Configure preprocessing material
    fn with_preprocessing(self, triples: usize, random_shares: usize) -> Self

    // Build the node
    fn build(self) -> Result<MPCNode>
}
}

Error Types

#![allow(unused)]
fn main() {
pub enum Error {
    // StoffelLang compilation failures
    CompilationError(String),

    // VM execution errors
    RuntimeError(String),

    // MPC protocol errors
    MPCError(String),

    // File/network IO errors
    IoError(std::io::Error),

    // Invalid parameters
    InvalidInput(String),

    // Missing function
    FunctionNotFound(String),

    // Network communication errors
    Network(String),

    // Configuration validation failures
    Configuration(String),

    // MPC preprocessing errors
    Preprocessing(String),

    // MPC computation errors
    Computation(String),

    // Generic error
    Other(String),
}

pub type Result<T> = std::result::Result<T, Error>;
}

Value Type

VM execution results:

#![allow(unused)]
fn main() {
pub enum Value {
    I64(i64),
    I32(i32),
    I16(i16),
    I8(i8),
    U64(u64),
    U32(u32),
    U16(u16),
    U8(u8),
    Float(i64),      // Fixed-point representation
    Bool(bool),
    String(String),
    Unit,            // Nil/void
    Object(usize),   // Reference to object
    Array(usize),    // Reference to array
    Share(ShareType, Vec<u8>),  // Secret-shared value
}
}

Prelude

For convenience, import all common types:

#![allow(unused)]
fn main() {
use stoffel_rust_sdk::prelude::*;

// Includes:
// - Stoffel, StoffelRuntime, Program
// - MPCClient, MPCServer, MPCNode
// - ProtocolType, ShareType
// - Value, FunctionInfo
// - Error, Result
}

Examples

Simple Local Execution

The most basic usage - compile and run locally without MPC:

use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let source = r#"
        def add(a: int64, b: int64) -> int64:
            return a + b

        main main() -> int64:
            return add(10, 20)
    "#;

    let result = Stoffel::compile(source)?
        .execute_local()?;

    println!("Result: {:?}", result);  // Output: I64(30)
    Ok(())
}

MPC Configuration

Configure for multi-party computation:

use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let source = r#"
        def secure_sum(a: secret int64, b: secret int64) -> secret int64:
            return a + b

        main main() -> int64:
            return 0
    "#;

    let runtime = Stoffel::compile(source)?
        .parties(5)           // 5-party MPC
        .threshold(1)         // Tolerate 1 Byzantine party
        .instance_id(42)      // Unique computation ID
        .build()?;

    // Test locally first
    let result = runtime.program().execute_local()?;
    println!("Local test: {:?}", result);

    // Access configuration
    if let Some((parties, threshold, instance)) = runtime.mpc_config() {
        println!("MPC: {} parties, threshold {}, instance {}",
                 parties, threshold, instance);
    }

    Ok(())
}

Complete MPC Workflow

End-to-end example with servers and clients:

use stoffel_rust_sdk::prelude::*;
use std::net::SocketAddr;

#[tokio::main]
async fn main() -> Result<()> {
    let source = r#"
        def compute(a: secret int64, b: secret int64) -> secret int64:
            return a * b + 100

        main main() -> int64:
            return 0
    "#;

    // Build runtime with MPC configuration
    let runtime = Stoffel::compile(source)?
        .parties(4)
        .threshold(1)
        .instance_id(1234)
        .build()?;

    // Create MPC servers
    let mut server0 = runtime.server(0)
        .with_preprocessing(10, 25)
        .build()?;

    let mut server1 = runtime.server(1)
        .with_preprocessing(10, 25)
        .build()?;

    // Configure peer connections
    let addr0: SocketAddr = "127.0.0.1:19200".parse().unwrap();
    let addr1: SocketAddr = "127.0.0.1:19201".parse().unwrap();

    server0.add_peer(1, addr1);
    server1.add_peer(0, addr0);

    // Start listeners
    server0.bind_and_listen(addr0).await?;
    server1.bind_and_listen(addr1).await?;

    // Initialize nodes
    server0.initialize_node()?;
    server1.initialize_node()?;

    // Connect peers
    server0.connect_to_peers().await?;
    server1.connect_to_peers().await?;

    // Create client with secret inputs
    let mut client = runtime.client(100)
        .with_inputs(vec![42, 17])
        .build()?;

    client.add_server(0, addr0);
    client.add_server(1, addr1);

    // Execute MPC
    client.connect_to_servers().await?;
    client.send_inputs().await?;
    let result = client.receive_outputs().await?;

    println!("MPC Result: {:?}", result);
    Ok(())
}

Bytecode Operations

Work with compiled bytecode:

use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let source = r#"
        def factorial(n: int64) -> int64:
            if n <= 1:
                return 1
            return n * factorial(n - 1)

        def fibonacci(n: int64) -> int64:
            if n <= 1:
                return n
            var a: int64 = 0
            var b: int64 = 1
            for i in 2..n:
                var temp = a + b
                a = b
                b = temp
            return b

        main main() -> int64:
            return factorial(5)
    "#;

    let runtime = Stoffel::compile(source)?.build()?;
    let program = runtime.program();

    // List available functions
    for func in program.list_functions()? {
        println!("Function: {} ({} params, {} registers)",
                 func.name, func.parameters.len(), func.register_count);
    }

    // Execute different functions
    let fact_result = program.execute_local_function("factorial")?;
    println!("factorial(5) = {:?}", fact_result);

    // Execute with arguments
    let fib_result = program.execute_local_with_args("fibonacci", vec![Value::I64(10)])?;
    println!("fibonacci(10) = {:?}", fib_result);

    // Save bytecode for later
    program.save("my_program.stfb")?;

    Ok(())
}

Loading Saved Bytecode

Load and execute previously compiled programs:

use stoffel_rust_sdk::prelude::*;
use std::fs;

fn main() -> Result<()> {
    // Load bytecode from file
    let bytecode = fs::read("my_program.stfb")?;

    let runtime = Stoffel::load(bytecode)?
        .parties(5)
        .threshold(1)
        .build()?;

    let result = runtime.program().execute_local()?;
    println!("Result: {:?}", result);

    Ok(())
}

Network Configuration from TOML

Use a configuration file for network settings:

# stoffel.toml
[network]
party_id = 0
bind_address = "127.0.0.1:9001"
bootstrap_address = "127.0.0.1:9000"
min_parties = 4

[mpc]
n_parties = 5
threshold = 1
instance_id = 12345
use stoffel_rust_sdk::prelude::*;

fn main() -> Result<()> {
    let runtime = Stoffel::compile_file("program.stfl")?
        .network_config_file("stoffel.toml")?
        .build()?;

    // Network config is automatically applied
    println!("Runtime configured from TOML");

    Ok(())
}

Error Handling

Comprehensive error handling example:

use stoffel_rust_sdk::prelude::*;
use stoffel_rust_sdk::error::Error;

fn main() {
    let source = r#"
        main main() -> int64:
            return 42
    "#;

    match run_mpc(source) {
        Ok(result) => println!("Success: {:?}", result),
        Err(Error::CompilationError(msg)) => {
            eprintln!("Compilation failed: {}", msg);
        }
        Err(Error::Configuration(msg)) => {
            eprintln!("Invalid configuration: {}", msg);
        }
        Err(Error::Network(msg)) => {
            eprintln!("Network error: {}", msg);
        }
        Err(Error::RuntimeError(msg)) => {
            eprintln!("Runtime error: {}", msg);
        }
        Err(e) => {
            eprintln!("Other error: {:?}", e);
        }
    }
}

fn run_mpc(source: &str) -> Result<Value> {
    let runtime = Stoffel::compile(source)?
        .parties(5)
        .threshold(1)
        .build()?;

    runtime.program().execute_local()
}

Using the CLI Template

The easiest way to get started:

# Create a new Rust MPC project
stoffel init my-mpc-app --template rust
cd my-mpc-app

# Build and run
cargo run

The generated project includes a complete example with:

  • SDK integration
  • StoffelLang program
  • MPC configuration
  • Ready-to-run code

Python SDK Overview

Status: Work in Progress

The Python SDK is currently under active development. The API described here reflects the target design. For a production-ready SDK today, see the Rust SDK.

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.

Repository

The Python SDK is being developed at: github.com/Stoffel-Labs/stoffel-python-sdk

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())

Development Status

Current implementation progress:

ComponentStatusNotes
Clean API Design✅ CompleteSeparation of concerns implemented
StoffelProgram🚧 In ProgressCompilation and VM operations
StoffelClient🚧 In ProgressNetwork communication interface
VM Bindings🚧 In ProgressFFI bindings to StoffelVM
MPC Network Integration📋 PlannedAwaiting MPC service infrastructure
Integration Tests📋 PlannedWith actual shared libraries

Current Alternative: Rust SDK

While the Python SDK is being developed, you can use the fully-functional Rust SDK which provides:

  • Complete compilation and VM execution
  • MPC configuration with HoneyBadger protocol
  • Network-based client/server architecture
  • Local testing capabilities

Contributing

The Python SDK is open source and contributions are welcome!

Next Steps

Installation

Status: Work in Progress

The Python SDK is under active development. Installation instructions will be finalized when the SDK reaches beta.

Repository

Clone the SDK repository to get started:

git clone https://github.com/Stoffel-Labs/stoffel-python-sdk.git
cd stoffel-python-sdk

Development Installation

For contributors and early adopters:

# With Poetry (recommended)
poetry install

# Or with pip in development mode
pip install -e .

Future Installation

Once the SDK reaches stable release, it will be available via pip:

pip install stoffel-python-sdk

Prerequisites

The Python SDK requires:

  • Python 3.8 or higher
  • StoffelVM shared library (libstoffel_vm.so / libstoffel_vm.dylib)
  • StoffelLang compiler (included with Stoffel CLI)

Building StoffelVM Shared Library

# Clone and build StoffelVM
git clone https://github.com/Stoffel-Labs/StoffelVM.git
cd StoffelVM
cargo build --release

# The shared library will be at:
# Linux: target/release/libstoffel_vm.so
# macOS: target/release/libstoffel_vm.dylib

Current Alternative

For production use today, the Rust SDK is fully functional:

# Add to your Cargo.toml
[dependencies]
stoffel-rust-sdk = { git = "https://github.com/Stoffel-Labs/stoffel-rust-sdk" }

Or use the CLI to create a Rust project:

stoffel init my-project --template rust

Using the Python Template

Even while the SDK is in development, you can scaffold a Python project structure:

stoffel init my-python-project --template python

This creates:

  • Project structure with pyproject.toml
  • StoffelLang program in stoffel/src/program.stfl
  • Python entry point ready for SDK integration
  • Test scaffolding with pytest

Next Steps

API Reference

Status: Work in Progress

This page documents the target API design for the Python SDK. The API is subject to change as development progresses.

StoffelProgram

Handles StoffelLang compilation and VM operations.

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

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

    # 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 execution
    def execute_locally(self, inputs: Dict[str, Any]) -> Any

Usage Example

from stoffel import StoffelProgram

program = StoffelProgram("my_program.stfl")
program.compile(optimize=True)
program.set_execution_params({
    "computation_id": "my_computation",
    "function_name": "main"
})

# Test locally
result = program.execute_locally({"a": 10, "b": 20})

StoffelClient

Manages MPC network communication.

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

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

    # 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]

Usage Example

from stoffel import StoffelClient

client = StoffelClient({
    "nodes": ["http://node1:9000", "http://node2:9000"],
    "client_id": "my_client",
    "program_id": "my_computation"
})

result = await client.execute_with_inputs(
    secret_inputs={"private_value": 42},
    public_inputs={"config": "standard"}
)

await client.disconnect()

Network Configuration

config = {
    "nodes": [
        "http://mpc-node1:9000",
        "http://mpc-node2:9000",
        "http://mpc-node3:9000"
    ],
    "client_id": "unique_client_id",
    "program_id": "computation_identifier",
    "coordinator_url": "http://coordinator:8080"  # Optional
}

Error Types

from stoffel.errors import (
    StoffelError,        # Base exception
    CompilationError,    # StoffelLang compilation failures
    RuntimeError,        # VM execution errors
    NetworkError,        # Connection failures
    MPCError,            # Protocol-level errors
    ConfigurationError   # Invalid parameters
)

Low-Level VM Access (Advanced)

For direct VM control:

from stoffel.vm import VirtualMachine, StoffelValue

vm = VirtualMachine()

# Register custom functions
def custom_op(a, b):
    return a * b + 42

vm.register_foreign_function("custom_op", custom_op)

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

Type Conversions

Python TypeStoffelLang Type
intint64
floatfloat (fixed-point)
strstring
boolbool
Nonenil
listarray
dictobject

See Also

Examples

Status: Work in Progress

These examples demonstrate the target API. Some functionality may not yet be implemented.

Basic Usage

Simple Computation

import asyncio
from stoffel import StoffelProgram, StoffelClient

async def main():
    # Compile the program
    program = StoffelProgram("add.stfl")
    program.compile()

    # Connect to MPC network
    client = StoffelClient({
        "nodes": ["http://node1:9000", "http://node2:9000", "http://node3:9000"],
        "client_id": "demo_client",
        "program_id": "addition"
    })

    # Execute with secret inputs
    result = await client.execute_with_inputs(
        secret_inputs={"a": 25, "b": 17}
    )

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

asyncio.run(main())

Local Testing

Test your program locally before deploying to MPC:

from stoffel import StoffelProgram

program = StoffelProgram("my_program.stfl")
program.compile()

# Test with sample inputs
result = program.execute_locally({
    "input_a": 100,
    "input_b": 200
})

print(f"Local result: {result}")

Use Case Examples

Healthcare Data Privacy

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

    result = await client.execute_with_inputs(
        secret_inputs={
            "patient_age": 45,
            "blood_pressure": 120,
            "cholesterol": 180
        },
        public_inputs={
            "analysis_type": "cardiovascular_risk"
        }
    )

    return result

Financial Computation

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

    result = await client.execute_with_inputs(
        secret_inputs={
            "income": 75000,
            "debt": 15000,
            "payment_history_score": 95
        },
        public_inputs={
            "model_version": "v2"
        }
    )

    return result

Secure Auction

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

    result = await client.execute_with_inputs(
        secret_inputs={
            "bid_amount": 1500,
            "max_price": 2000
        },
        public_inputs={
            "auction_id": "auction_123",
            "item_category": "electronics"
        }
    )

    return result

Error Handling

from stoffel import StoffelClient
from stoffel.errors import NetworkError, MPCError, CompilationError

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

    try:
        result = await client.execute_with_inputs(
            secret_inputs={"value": 42}
        )
        return result
    except NetworkError as e:
        print(f"Connection failed: {e}")
    except MPCError as e:
        print(f"MPC protocol error: {e}")
    except CompilationError as e:
        print(f"Program compilation failed: {e}")
    finally:
        await client.disconnect()

Working Examples Today

While the Python SDK is in development, you can:

1. Use the Rust SDK

See Rust SDK Examples for production-ready code.

2. Create a Python Project Template

stoffel init my-python-project --template python
cd my-python-project

This creates a project structure ready for SDK integration:

my-python-project/
├── pyproject.toml
├── src/my_python_project/
│   └── main.py
├── stoffel/
│   └── src/program.stfl
└── tests/
    └── test_main.py

3. Compile and Run StoffelLang Directly

# Compile and run with the CLI
stoffel compile stoffel/src/program.stfl --binary
stoffel run

Repository Examples

The Python SDK repository includes example code:

git clone https://github.com/Stoffel-Labs/stoffel-python-sdk.git
cd stoffel-python-sdk

# Run examples (when available)
poetry run python examples/simple_api_demo.py
poetry run python examples/complete_workflow.py

Next Steps

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