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:
Documentation Structure
This documentation is organized to guide you through the Stoffel ecosystem:
- Getting Started: Installation, quick start, and first project
- Stoffel CLI: Comprehensive guide to the command-line interface
- StoffelLang: Programming language syntax and compilation
- StoffelVM: Virtual machine architecture and usage
- Python SDK: Python integration and API reference
- Architecture: System design and technical details
- Development: Contributing and building from source
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:
- Trust a third party with their sensitive data, or
- 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:
- Secret Sharing: Each party's private input is split into multiple "shares" using cryptographic techniques
- Distributed Computation: The computation is performed on these shares across multiple nodes
- 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
Technology | Privacy Level | Performance | Use Cases |
---|---|---|---|
MPC | High - inputs remain secret | Moderate | Multi-party computation |
Homomorphic Encryption | High - single party holds data | Low | Outsourced computation |
Differential Privacy | Medium - statistical privacy | High | Data analysis/sharing |
Secure Enclaves | High - hardware-based | High | Trusted 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? - How Stoffel solves MPC development challenges
- Ecosystem Overview - Complete overview of Stoffel's components
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?
- Get Started: Install and create your first MPC project
- Explore the Ecosystem: Understand how all the components work together
- See Examples: Real applications built with Stoffel
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:
- Install Stoffel - Set up the development environment
- Create Your First Project - Build a simple MPC application
- Learn StoffelLang - Master the programming language
- Explore the CLI - Understand all available commands and options
- 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:
- Check the individual repository README files for component-specific instructions
- GitHub Issues: Report issues at the respective repository
- Build logs: Check cargo output for specific error messages
Next Steps
Now that you have Stoffel installed:
- Quick Start: Create your first project in 5 minutes
- Basic Usage: Learn the essential Stoffel commands
- 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:
- Secret Sharing: Your inputs (25 and 17) were automatically split into shares
- Distributed Computation: Each party computed on shares without seeing the original values
- 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
, andstoffel deploy
are currently under development. The core workflow usingstoffel compile
andstoffel-run
is fully functional.
What's Next?
Now that you've created your first MPC application:
- Basic Usage: Learn all the essential Stoffel CLI commands
- Your First MPC Project: Build a more complex privacy-preserving application
- StoffelLang Overview: Deep dive into the programming language
- 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
, andstoffel 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:
- Your First MPC Project: Build a complete real-world application
- CLI Overview: Detailed CLI reference and advanced features
- StoffelLang Overview: Learn the programming language in depth
- 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:
- Submit encrypted salary data for specific roles
- Compute statistics (average, median, percentiles) across all companies
- Receive market insights without seeing other companies' data
- 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:
- Explore Advanced Features: Learn about advanced development workflows
- Optimize Performance: Understand VM optimization techniques
- Production Deployment: Deploy to real MPC networks
- Community Templates: Explore more use case templates
Real-World Applications
This same pattern can be applied to many privacy-preserving use cases:
- Healthcare: Multi-hospital research without sharing patient data
- Finance: Risk assessment across banks without exposing portfolios
- Marketing: Cross-company analytics without sharing customer data
- Government: Inter-agency intelligence without data exposure
- Supply Chain: Collaborative optimization without revealing trade secrets
The Stoffel framework makes all of these applications achievable with the same development patterns you've learned here!
Stoffel CLI Overview
The Stoffel CLI is a comprehensive command-line interface that provides everything you need to develop, build, and deploy privacy-preserving applications using secure Multi-Party Computation (MPC).
Design Philosophy
The Stoffel CLI is designed with the following principles:
- Developer-Friendly: Intuitive commands that follow familiar patterns from tools like
cargo
andnpm
- Template-Driven: Project templates for different use cases and programming languages
- Integrated Workflow: Seamless integration between development, compilation, and deployment
- Extensible: Plugin system for future enhancements and community contributions
Core Commands
Project Management
# Initialize new projects
stoffel init my-project # Default StoffelLang project
stoffel init --template python webapp # Python integration template
stoffel init --lib crypto-utils # Create a library project
stoffel init --interactive # Interactive project setup
Compilation
# Compile StoffelLang programs
stoffel compile # Compile all files in src/
stoffel compile src/main.stfl # Compile specific file
stoffel compile --binary # Generate VM-compatible binaries
stoffel compile -O3 # Maximum optimization
Development
# Development server with hot reloading
stoffel dev # Default: 5 parties, port 8080
stoffel dev --parties 7 --port 3000 # Custom configuration
stoffel dev --field bn254 # Different cryptographic field
Building and Deployment
# Build for different targets
stoffel build # Debug build
stoffel build --release # Production build
stoffel build --target wasm # WebAssembly target
# Deploy to various environments
stoffel deploy --target tee # TEE deployment
stoffel deploy --env production # Production environment
Available Templates
The CLI provides templates for different development scenarios:
Language-Specific Templates
python
: Full Python SDK integration with Poetry and pytestrust
: Rust FFI integration with StoffelVM (development skeleton)typescript
: TypeScript/Node.js client integrationsolidity
: Smart contracts with MPC result verification
Use-Case Templates
web3-auction
: Private auction implementationweb3-voting
: Secure voting systemweb-healthcare
: Healthcare data privacyweb-fintech
: Financial computation privacydesktop-messaging
: Secure messaging application
Project Structure
When you create a new project, the CLI generates a standard structure:
my-mpc-project/
├── Stoffel.toml # Project configuration
├── src/ # StoffelLang source files
│ ├── main.stfl # Main program entry point
│ └── lib.stfl # Library functions (for --lib projects)
├── tests/ # Test files
│ └── integration.stfl # Integration tests
└── README.md # Project documentation
Python Template Structure
For Python integration projects:
my-python-project/
├── Stoffel.toml # Stoffel configuration
├── pyproject.toml # Poetry configuration
├── src/
│ ├── main.py # Python implementation
│ └── secure_computation.stfl # StoffelLang program
├── tests/
│ └── test_main.py # Python tests
└── README.md
Configuration
Stoffel.toml
The main configuration file for Stoffel projects:
[package]
name = "my-secure-app"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2024"
[mpc]
protocol = "honeybadger"
parties = 5
threshold = 1
field = "bls12-381"
[build]
optimization_level = 2
target = "vm"
output_dir = "build"
[dev]
hot_reload = true
simulation_mode = true
port = 8080
[dependencies]
# Future: Package dependencies will be listed here
MPC Configuration
The CLI supports configurable MPC parameters:
- Parties: Number of parties in the MPC computation (minimum 5 for security)
- Threshold: Maximum number of corrupted parties =
(parties - 1) / 3
- Cryptographic Fields: BLS12-381 (default), BN254, Secp256k1, Prime61
- Protocol: Currently HoneyBadger MPC (more protocols planned)
Development Server Features
The stoffel dev
command provides:
- Hot Reloading: Automatic recompilation and restart when files change
- MPC Simulation: Local simulation of multi-party computation for testing
- Debug Interface: Web interface for debugging MPC execution
- Live Logs: Real-time logs from all simulated parties
- Performance Metrics: Timing and communication overhead analysis
Help System
The CLI provides comprehensive help for all commands:
stoffel --help # Main help
stoffel init --help # Command-specific help
stoffel compile --binary --help # Flag-specific help
Future Features
Planned enhancements for the CLI:
- Package Manager:
stoffel add
andstoffel publish
for dependency management - Testing Framework:
stoffel test
with MPC-specific test patterns - Deployment Tools: Enhanced deployment to cloud providers and Kubernetes
- Plugin System: Community plugins for specialized workflows
- IDE Integration: Language server protocol support for editors
Examples
Quick Start
# Create and run a simple MPC project
stoffel init hello-mpc
cd hello-mpc
stoffel dev
# In another terminal
curl http://localhost:8080/execute
Python Integration
# Create Python project with MPC
stoffel init secure-analytics --template python
cd secure-analytics
# Install Python dependencies
poetry install
# Start development
stoffel dev --parties 7
Production Deployment
# Build optimized release
stoffel build --release --target production
# Deploy to TEE environment
stoffel deploy --target tee --config production.toml
Next Steps
- Project Management: Learn about creating and managing projects
- Development Workflow: Understand the development process
- Building and Deployment: Build and deploy your applications
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 stringsnil
: 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
- Lexical Analysis: Tokenizes source code
- Parsing: Builds Abstract Syntax Tree (AST)
- Type Checking: Verifies type correctness and infers types
- Optimization: Applies various optimization passes
- 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: Detailed syntax guide with examples
- Compilation: Understanding the compilation process
Syntax and Examples
This page provides a comprehensive guide to StoffelLang syntax, featuring practical examples and detailed explanations of the language's features.
Basic Elements
Comments
StoffelLang uses #
for comments:
# This is a single-line comment
let x = 42 # Inline comment
# Multi-line comments can be created
# by using multiple single-line comments
Identifiers and Keywords
Valid identifiers:
- Must start with a letter or underscore
- Can contain letters, numbers, and underscores
- Case-sensitive
let my_variable = 10
let _private_value = "secret"
let camelCase = true
let snake_case_name = "Alice"
Reserved keywords:
let var proc type object enum
if else elif while for in
return yield break continue
true false nil secret discard
Variables and Types
Variable Declarations
StoffelLang supports immutable (let
) and mutable (var
) variables:
# Immutable variables
let name: string = "Alice"
let age: int64 = 25
let is_active = true # Type inference
# Mutable variables
var counter: int64 = 0
var status = "pending" # Type inference
Type Annotations
Explicit type annotations use colon syntax:
let count: int64 = 100
let message: string = "Hello"
let flag: bool = false
let empty: nil = nil
Type Inference
StoffelLang can infer types from context:
let inferred_int = 42 # int64
let inferred_string = "text" # string
let inferred_bool = true # bool
Primitive Types
Integer Types
StoffelLang primarily uses int64
:
let small_number: int64 = 10
let large_number: int64 = 9223372036854775807
let negative: int64 = -42
Boolean Type
let is_ready: bool = true
let is_complete: bool = false
# Boolean operations
let result = true and false # false
let combined = true or false # true
let negated = not true # false
String Type
let greeting: string = "Hello, world!"
let empty_string: string = ""
let multiline = "First line\nSecond line"
# String concatenation
let full_name = "Alice" + " " + "Smith"
let message = "Count: " + $42 # Convert int to string with $
Nil Type
let nothing: nil = nil
let maybe_value = nil # Type inferred as nil
Secret Types
The secret
keyword creates MPC-aware types:
# Secret primitive types
let secret_age: secret int64 = 25
let secret_name: secret string = "Bob"
let secret_flag: secret bool = true
# Secret values in computations
proc secure_comparison(a: secret int64, b: secret int64): secret bool =
return a > b
# Mixed public/secret operations
proc threshold_check(secret_value: secret int64, public_threshold: int64): secret bool =
return secret_value >= public_threshold
Functions
Function Definitions
Functions use the proc
keyword:
# Basic function
proc greet(name: string): string =
return "Hello, " + name
# Function with multiple parameters
proc add(a: int64, b: int64): int64 =
return a + b
# Function without return value (implicit nil return)
proc log_message(msg: string) =
print(msg)
# Function with secret parameters
proc secure_multiply(a: secret int64, b: secret int64): secret int64 =
return a * b
Function Calls
# Basic function calls
let result = add(10, 20)
let greeting = greet("Alice")
# Nested function calls
let complex_result = add(add(1, 2), add(3, 4))
# Secret function calls
let secret_result = secure_multiply(secret(5), secret(6))
Functions with Local Variables
proc calculate_area(length: int64, width: int64): int64 =
let area = length * width
let formatted_msg = "Area calculated: " + $area
print(formatted_msg)
return area
Control Flow
If Statements
# Basic if statement
if age >= 18:
print("Adult")
# If-else
if temperature > 30:
print("Hot")
else:
print("Not hot")
# If-elif-else
if score >= 90:
print("A grade")
elif score >= 80:
print("B grade")
elif score >= 70:
print("C grade")
else:
print("Below C grade")
If Expressions
If statements can be used as expressions:
let status = if age >= 18: "adult" else: "minor"
let max_value = if a > b: a else: b
While Loops
# Basic while loop
var count = 0
while count < 10:
print("Count: " + $count)
count = count + 1
# While with complex condition
var running = true
var attempts = 0
while running and attempts < 5:
# Do something
attempts = attempts + 1
if attempts >= 3:
running = false
For Loops
# Range-based for loops
for i in 0..10:
print("Number: " + $i)
# For loop with step (conceptual - syntax may vary)
for i in 0..20:
if i % 2 == 0:
print("Even: " + $i)
Data Structures
Object Types
# Object type definition
type Person = object
name: string
age: int64
email: string
is_active: bool
# Object with secret fields
type SecurePerson = object
name: string
age: secret int64
salary: secret int64
public_id: int64
Object Creation and Access
# Creating objects
let alice = Person(
name: "Alice Smith",
age: 30,
email: "alice@example.com",
is_active: true
)
# Accessing fields
let person_name = alice.name
let person_age = alice.age
# Creating objects with secret fields
let secure_employee = SecurePerson(
name: "Bob Jones",
age: secret(35),
salary: secret(75000),
public_id: 12345
)
Nested Objects
type Address = object
street: string
city: string
country: string
type Employee = object
personal: Person
address: Address
employee_id: int64
let employee = Employee(
personal: Person(
name: "Carol Davis",
age: 28,
email: "carol@company.com",
is_active: true
),
address: Address(
street: "123 Main St",
city: "Tech City",
country: "USA"
),
employee_id: 98765
)
# Accessing nested fields
let employee_name = employee.personal.name
let employee_city = employee.address.city
Enum Types (Planned)
# Basic enum
type Status = enum
Active
Inactive
Pending
Suspended
# Enum with values
type Priority = enum
Low = 1
Medium = 2
High = 3
Critical = 4
# Using enums
let current_status = Status.Active
let task_priority = Priority.High
Operators
Arithmetic Operators
let a = 10
let b = 3
let sum = a + b # 13
let difference = a - b # 7
let product = a * b # 30
let quotient = a / b # 3 (integer division)
let remainder = a % b # 1
Comparison Operators
let x = 10
let y = 20
let equal = x == y # false
let not_equal = x != y # true
let less_than = x < y # true
let less_equal = x <= y # true
let greater_than = x > y # false
let greater_equal = x >= y # false
Logical Operators
let a = true
let b = false
let logical_and = a and b # false
let logical_or = a or b # true
let logical_not = not a # false
String Operations
let first = "Hello"
let second = "World"
let combined = first + " " + second # "Hello World"
let with_number = "Count: " + $42 # "Count: 42"
Advanced Features
Working with Secret Types
# Secret arithmetic
proc secure_calculation(a: secret int64, b: secret int64, c: int64): secret int64 =
let secret_sum = a + b
let mixed_operation = secret_sum * c # Public value used with secret
return mixed_operation
# Secret comparisons
proc secure_threshold(value: secret int64, threshold: int64): secret bool =
return value > threshold
# Multiple secret operations
proc complex_secure_calc(
secret_a: secret int64,
secret_b: secret int64,
public_factor: int64
): secret int64 =
let temp1 = secret_a + secret_b
let temp2 = secret_a * secret_b
let result = (temp1 + temp2) * public_factor
return result
Error Handling (Planned)
# Try-catch blocks (future feature)
try:
let result = risky_operation()
print("Success: " + $result)
catch error:
print("Error occurred: " + error.message)
Pattern Matching (Planned)
# Match expressions (future feature)
let result = match status:
Status.Active: "Currently active"
Status.Inactive: "Not active"
Status.Pending: "Waiting for approval"
_: "Unknown status"
Best Practices
Naming Conventions
# Use snake_case for variables and functions
let user_name = "alice"
let max_retry_count = 5
proc calculate_total_cost(base_price: int64, tax_rate: int64): int64 =
return base_price + (base_price * tax_rate / 100)
# Use PascalCase for types
type UserAccount = object
user_id: int64
account_balance: secret int64
Type Safety
# Prefer explicit types for public interfaces
proc public_api(user_id: int64, amount: secret int64): bool =
# Implementation
return true
# Use type inference for local variables
proc internal_calculation() =
let temp = 42 # Type inferred as int64
let message = "Processing" # Type inferred as string
Secret Type Usage
# Clearly distinguish between public and secret data
proc process_transaction(
public_user_id: int64,
secret_amount: secret int64,
public_currency: string
): secret bool =
# Only secret operations on secret data
let is_valid_amount = secret_amount > 0
return is_valid_amount
# Avoid unnecessary secret wrapping
proc calculate_fee(amount: int64): int64 = # Public calculation
return amount * 5 / 100
proc apply_secret_fee(secret_amount: secret int64): secret int64 =
let fee_rate = 5 # Public constant
return secret_amount * fee_rate / 100 # Secret result
Function Organization
# Small, focused functions
proc validate_age(age: int64): bool =
return age >= 0 and age <= 150
proc validate_email(email: string): bool =
# Simplified validation
return email.length > 0
proc create_user(name: string, age: int64, email: string): Person =
# Use validation functions
if not validate_age(age):
# Error handling (simplified)
print("Invalid age")
if not validate_email(email):
print("Invalid email")
return Person(
name: name,
age: age,
email: email,
is_active: true
)
Common Patterns
Data Processing
proc process_user_data(user: Person): string =
let age_category = if user.age < 18:
"minor"
elif user.age < 65:
"adult"
else:
"senior"
let status_text = if user.is_active: "active" else: "inactive"
return user.name + " (" + age_category + ", " + status_text + ")"
Secret Computation Patterns
# Secure comparison with public result indication
proc secure_age_check(secret_age: secret int64, min_age: int64): bool =
let meets_requirement = secret_age >= min_age
# In practice, this would use proper MPC reveal operations
return true # Simplified for syntax example
# Secure aggregation pattern
proc secure_sum(values: [secret int64; 5]): secret int64 =
var total: secret int64 = 0
for i in 0..5:
# Note: Array indexing syntax may vary in implementation
# This is a conceptual example
total = total + values[i]
return total
This syntax guide covers the current StoffelLang implementation and provides a foundation for understanding the language's structure and capabilities.
Compilation
This page explains the StoffelLang compilation process, from source code to executable bytecode, including optimization techniques and debugging capabilities.
Overview
StoffelLang uses a multi-stage compilation pipeline that transforms human-readable source code into efficient bytecode for the StoffelVM. The compiler is designed to provide excellent error messages, strong type checking, and optimizations specific to MPC computations.
Compilation Pipeline
Stage 1: Lexical Analysis
The lexer tokenizes the source code, breaking it into meaningful tokens:
Source: let x: int64 = 42
Tokens: [LET, IDENTIFIER("x"), COLON, IDENTIFIER("int64"), ASSIGN, INT_LITERAL(42)]
Key Features:
- Indentation-based: Uses 2-space indentation (tabs not allowed)
- Unicode support: Full UTF-8 string and identifier support
- Error recovery: Continues parsing after errors to find more issues
Stage 2: Parsing
The parser builds an Abstract Syntax Tree (AST) from the token stream:
AST Node: VariableDeclaration {
name: "x",
type_annotation: Some(Identifier("int64")),
value: Some(Literal(Int(42))),
is_mutable: false,
is_secret: false,
location: SourceLocation { line: 1, column: 1 }
}
Parser Features:
- Recursive descent: Predictable parsing with clear error messages
- Location tracking: Every AST node includes source location
- Error recovery: Attempts to continue parsing after syntax errors
Stage 3: Semantic Analysis
The semantic analyzer performs type checking and builds the symbol table:
Type Checking:
# This would produce a type error
let name: string = 42 # Error: Cannot assign int64 to string
# This works correctly
let age: int64 = 42 # OK: Types match
Symbol Resolution:
proc add(a: int64, b: int64): int64 =
return a + b # Resolves 'a' and 'b' to parameters
let result = add(10, 20) # Resolves 'add' to function definition
Stage 4: Code Generation
Generates StoffelVM bytecode from the validated AST:
StoffelLang: Bytecode:
let x: int64 = 42 LDI R0, 42
STORE x, R0
proc add(a, b): FUNCTION add:
return a + b LOAD R0, a
LOAD R1, b
ADD R0, R0, R1
RET R0
Using the Compiler
Basic Compilation
# Compile a single file
stoffel compile src/main.stfl
# Compile to VM-compatible binary
stoffel compile src/main.stfl --binary --output program.stfbin
# Compile all files in src/
stoffel compile
Compilation Options
Optimization Levels
# No optimization (fastest compilation, good for debugging)
stoffel compile src/main.stfl -O0
# Basic optimizations (balanced)
stoffel compile src/main.stfl -O1
# Standard optimizations (recommended for production)
stoffel compile src/main.stfl -O2
# Maximum optimizations (slowest compilation, best performance)
stoffel compile src/main.stfl -O3
Output Formats
# Default bytecode format
stoffel compile src/main.stfl
# VM-compatible binary (for execution)
stoffel compile src/main.stfl --binary --output app.stfbin
# Specify custom output location
stoffel compile src/main.stfl --output custom/path/program.stfbin
Debug Information
# Include debug symbols
stoffel compile src/main.stfl --debug
# Print intermediate representations
stoffel compile src/main.stfl --print-ir
# Verbose compilation output
stoffel compile src/main.stfl --verbose
Optimization Techniques
Constant Folding
The compiler evaluates constant expressions at compile time:
# Source code
let result = 2 + 3 * 4
# Optimized to
let result = 14
Dead Code Elimination
Removes unreachable code:
# Source code
proc example(flag: bool) =
if true:
print("Always executed")
else:
print("Never executed") # Removed by optimizer
# Optimized to
proc example(flag: bool) =
print("Always executed")
Function Inlining
Small functions may be inlined at call sites:
# Source code
proc square(x: int64): int64 =
return x * x
let result = square(5)
# May be optimized to
let result = 5 * 5
Secret Operation Optimization
Special optimizations for MPC operations:
# Source code
let a: secret int64 = 10
let b: secret int64 = 20
let sum = a + b
let product = a * b
# Compiler may batch secret operations for efficiency
Error Handling
Syntax Errors
Clear error messages with source locations:
Error: Unexpected token 'let'
--> src/main.stfl:5:3
|
5 | let x = 42
| ^^^ Expected expression, found 'let'
|
Help: Variable declarations must be at the top level of a block
Type Errors
Detailed type mismatch information:
Error: Type mismatch in assignment
--> src/main.stfl:8:12
|
8 | let name: string = 42
| ------ ^^ Expected 'string', found 'int64'
| |
| Variable declared as 'string' here
|
Help: Convert the integer to string: "42" or $42
Semantic Errors
Context-aware error messages:
Error: Cannot find value 'undefined_var' in this scope
--> src/main.stfl:12:15
|
12 | return undefined_var + 10
| ^^^^^^^^^^^^
|
Help: Did you mean 'defined_var'? (defined at line 3)
Intermediate Representations
Viewing IR with --print-ir
stoffel compile src/main.stfl --print-ir
Output includes:
- Tokens: Lexical analysis output
- AST: Parsed syntax tree
- Type Information: Resolved types and symbols
- 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 Level | Compile Time | Runtime Performance |
---|---|---|
-O0 | Fastest | Basic |
-O1 | Fast | Good |
-O2 | Medium | Better |
-O3 | Slowest | Best |
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
- Use --print-ir to see what the compiler generated
- Start with -O0 for debugging, optimize later
- Check types explicitly rather than relying on inference
- Use --verbose to see detailed compilation steps
Performance Issues
- Profile with --trace-instr during execution
- Try different optimization levels
- Review generated bytecode with --disassemble
- 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 consolecreate_object
: Create new objectscreate_array
: Create new arraysget_field
/set_field
: Object/array field accessarray_length
/array_push
: Array operationscreate_closure
/call_closure
: Closure operationsget_upvalue
/set_upvalue
: Upvalue managementtype
: 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: Detailed instruction set reference
- Using the VM: Practical examples and integration patterns
- Built-in Functions: Standard library reference
Instructions and Types
Using the VM
Built-in Functions
Python SDK Overview
The Stoffel Python SDK provides a clean, high-level interface for integrating Stoffel's secure Multi-Party Computation capabilities into Python applications. It offers a developer-friendly API that abstracts away cryptographic complexity while maintaining clear semantics for public and secret data.
Design Philosophy
The SDK is built around two core principles:
Separation of Concerns
- StoffelProgram: Handles StoffelLang compilation, VM operations, and execution parameters
- StoffelClient: Manages MPC network communication, data handling, and result reconstruction
Explicit Data Visibility
The API makes a clear distinction between:
- Secret Inputs: Private data that gets secret-shared across MPC nodes
- Public Inputs: Configuration and parameters visible to all nodes
Core Components
StoffelProgram - VM Operations
Responsible for local program management and compilation:
from stoffel import StoffelProgram
# Create and compile a program
program = StoffelProgram("secure_add.stfl")
program.compile(optimize=True)
# Set execution parameters
program.set_execution_params({
"computation_id": "secure_addition",
"function_name": "main",
"expected_inputs": ["a", "b", "threshold"]
})
# Test locally before MPC execution
result = program.execute_locally({"a": 25, "b": 17})
StoffelClient - Network Operations
Handles MPC network communication and data management:
from stoffel import StoffelClient
# Configure MPC network connection
client = StoffelClient({
"nodes": [
"http://mpc-node1:9000",
"http://mpc-node2:9000",
"http://mpc-node3:9000"
],
"client_id": "client_001",
"program_id": "secure_addition"
})
# Execute with explicit public/secret inputs
result = await client.execute_with_inputs(
secret_inputs={"a": 25, "b": 17}, # Private data
public_inputs={"threshold": 50} # Public configuration
)
Quick Start
Simple MPC Computation
import asyncio
from stoffel import StoffelProgram, StoffelClient
async def main():
# 1. Program compilation and setup
program = StoffelProgram("secure_add.stfl")
program.compile()
program.set_execution_params({
"computation_id": "secure_addition",
"function_name": "main",
"expected_inputs": ["a", "b"]
})
# 2. MPC network client setup
client = StoffelClient({
"nodes": ["http://mpc-node1:9000", "http://mpc-node2:9000", "http://mpc-node3:9000"],
"client_id": "my_client",
"program_id": "secure_addition"
})
# 3. Execute secure computation
result = await client.execute_with_inputs(
secret_inputs={"a": 25, "b": 17}
)
print(f"Secure computation result: {result}")
await client.disconnect()
asyncio.run(main())
Minimal One-Liner Usage
import asyncio
from stoffel import StoffelClient
async def main():
client = StoffelClient({
"nodes": ["http://mpc-node1:9000", "http://mpc-node2:9000", "http://mpc-node3:9000"],
"client_id": "my_client",
"program_id": "my_secure_program"
})
result = await client.execute_with_inputs(
secret_inputs={"user_data": 123, "private_value": 456},
public_inputs={"config_param": 100}
)
print(f"Result: {result}")
await client.disconnect()
asyncio.run(main())
API Reference
StoffelProgram
class StoffelProgram:
def __init__(self, source_file: Optional[str] = None)
# Compilation and loading
def compile(self, optimize: bool = True) -> str
def load_program(self) -> None
# Execution configuration
def set_execution_params(self, params: Dict[str, Any]) -> None
def get_computation_id(self) -> str
def get_program_info(self) -> Dict[str, Any]
# Local testing
def execute_locally(self, inputs: Dict[str, Any]) -> Any
StoffelClient
class StoffelClient:
def __init__(self, network_config: Dict[str, Any])
# Recommended API - explicit input types
async def execute_with_inputs(
self,
secret_inputs: Optional[Dict[str, Any]] = None,
public_inputs: Optional[Dict[str, Any]] = None
) -> Any
# Individual input management
def set_secret_input(self, name: str, value: Any) -> None
def set_public_input(self, name: str, value: Any) -> None
def set_inputs(
self,
secret_inputs: Optional[Dict[str, Any]] = None,
public_inputs: Optional[Dict[str, Any]] = None
) -> None
# Connection management
async def connect(self) -> None
async def disconnect(self) -> None
def is_ready(self) -> bool
def get_connection_status(self) -> Dict[str, Any]
# Legacy API (backward compatibility)
async def execute_program_with_inputs(self, inputs: Dict[str, Any]) -> Any
def set_private_data(self, name: str, value: Any) -> None
async def execute_program(self) -> Any
Network Configuration
Direct Node Connection
# Direct connection to known MPC nodes
client = StoffelClient({
"nodes": [
"http://mpc-node1:9000",
"http://mpc-node2:9000",
"http://mpc-node3:9000"
],
"client_id": "your_client_id",
"program_id": "your_program_id"
})
Optional Coordinator Integration
# With coordinator for metadata exchange
client = StoffelClient({
"nodes": [
"http://mpc-node1:9000",
"http://mpc-node2:9000",
"http://mpc-node3:9000"
],
"coordinator_url": "http://coordinator:8080", # Optional
"client_id": "your_client_id",
"program_id": "your_program_id"
})
Usage Patterns
Healthcare Data Privacy
async def secure_health_analysis():
client = StoffelClient(config)
result = await client.execute_with_inputs(
secret_inputs={
"patient_age": 45,
"medical_history": encoded_history,
"test_results": lab_values
},
public_inputs={
"analysis_type": "risk_assessment",
"threshold_values": risk_thresholds
}
)
return result
Financial Computation
async def secure_credit_score():
client = StoffelClient(config)
result = await client.execute_with_inputs(
secret_inputs={
"salary": 75000,
"credit_history": credit_data,
"debt_ratio": 0.3
},
public_inputs={
"scoring_model": "fico_v9",
"market_conditions": current_rates
}
)
return result
Multi-Party Auction
async def secure_auction():
client = StoffelClient(config)
result = await client.execute_with_inputs(
secret_inputs={
"my_bid": 1000,
"max_budget": 5000
},
public_inputs={
"auction_id": "item_12345",
"auction_rules": rules_config
}
)
return result
Advanced Features
Low-Level VM Access
For specialized use cases requiring direct VM control:
from stoffel.vm import VirtualMachine, StoffelValue
# Direct VM instantiation
vm = VirtualMachine()
# Register custom foreign functions
def custom_function(arg1, arg2):
return arg1 * arg2 + 42
vm.register_foreign_function("custom_op", custom_function)
# Execute with arguments
result = vm.execute_with_args("main", [
StoffelValue.integer(100),
StoffelValue.string("test")
])
Error Handling
from stoffel.mpc import MPCError, NetworkError, ComputationError
try:
result = await client.execute_with_inputs(
secret_inputs={"value": 123},
public_inputs={"param": 456}
)
except NetworkError as e:
print(f"Network issue: {e}")
except ComputationError as e:
print(f"MPC computation failed: {e}")
except MPCError as e:
print(f"General MPC error: {e}")
Installation and Setup
Prerequisites
- Python 3.8 or higher
- StoffelVM shared library (
libstoffel_vm.so
or equivalent) - StoffelLang compiler (for
.stfl
compilation)
Installation Options
# With Poetry (recommended)
poetry install
# With pip
pip install stoffel-python-sdk
# Development installation
git clone https://github.com/stoffel-labs/stoffel-python-sdk.git
cd stoffel-python-sdk
poetry install
Examples and Testing
The SDK includes comprehensive examples:
# Simple API demonstration
poetry run python examples/simple_api_demo.py
# Complete architecture example
poetry run python examples/correct_flow.py
# Advanced VM operations
poetry run python examples/vm_example.py
Development Status
Current implementation status:
- ✅ Clean API Design: Proper separation of concerns implemented
- ✅ StoffelProgram: Compilation and VM operations (ready for integration)
- ✅ StoffelClient: Network communication interface (ready for MPC integration)
- ✅ VM Bindings: FFI bindings to StoffelVM
- 🚧 MPC Network Integration: Awaiting actual MPC service infrastructure
- 🚧 StoffelLang Integration: Compiler integration in progress
- 📋 Integration Tests: With actual shared libraries and MPC networks
Architecture Benefits
Clean Separation
- VM Operations: Isolated in StoffelProgram for local testing and compilation
- Network Communication: Handled by StoffelClient for MPC operations
- Clear Boundaries: Easy to understand and extend
Type Safety
- Explicit Input Types: Clear distinction between secret and public data
- Runtime Safety: Proper error handling and validation
- Development Safety: Type hints throughout the codebase
Extensibility
- Plugin Architecture: Ready for additional protocol backends
- Foreign Functions: Easy integration with existing Python libraries
- Modular Design: Components can be used independently
Next Steps
To get started with the Stoffel Python SDK:
- Installation: Set up the development environment
- API Reference: Detailed API documentation
- Examples: Comprehensive usage examples
Installation
API Reference
Examples
Protocol Overview
Implementation Details
System Architecture
This section provides an overview of the complete Stoffel system architecture and how the various components interact.
Overall System Design
┌─────────────────────────────────────────────────────────────────┐
│ Stoffel Ecosystem │
├─────────────────────────────────────────────────────────────────┤
│ Developer Interface Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Stoffel CLI │ │ Python SDK │ │ IDEs & │ │
│ │ │ │ │ │ Editors │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Compilation Layer │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ StoffelLang │ │ Bytecode │ │
│ │ Compiler │→ │ Generator │ │
│ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Execution Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ StoffelVM │ │ Runtime │ │ Standard │ │
│ │ Core │ │ System │ │ Library │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Protocol Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ MPC Proto- │ │ Network │ │ Crypto │ │
│ │ cols │ │ Layer │ │ Primitives │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Component Interactions
Development Workflow
- Project Creation: Stoffel CLI creates project structure with templates
- Code Writing: Developers write StoffelLang programs with MPC primitives
- Compilation: StoffelLang compiler generates optimized VM bytecode
- Testing: Local VM execution for development and testing
- Deployment: MPC network deployment with protocol integration
Runtime Execution
- Program Loading: StoffelVM loads compiled bytecode
- Secret Sharing: Input data is secret-shared across MPC nodes
- Secure Computation: VM executes with MPC protocol integration
- 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:
-
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
-
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:
-
Modular Design
- Clear separation of concerns
- Plugin system for new instructions
- Customizable optimization passes
-
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:
-
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
-
Communication Efficiency
- Reduced number of memory access operations
- Fewer rounds of communication in Multi-Party Computation (MPC) contexts
- More efficient instruction encoding
-
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
- 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
- Instruction Fetch: Retrieve next instruction from program counter
- Decode: Parse instruction opcode and operands
- Execute: Perform operation with register/memory access
- 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!