Examples

Simple Local Execution

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

use stoffel_rust_sdk::prelude::*;

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

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

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

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

MPC Configuration

Configure for multi-party computation:

use stoffel_rust_sdk::prelude::*;

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

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

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

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

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

    Ok(())
}

Complete MPC Workflow

End-to-end example with servers and clients:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Bytecode Operations

Work with compiled bytecode:

use stoffel_rust_sdk::prelude::*;

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

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

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

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

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

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

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

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

    Ok(())
}

Loading Saved Bytecode

Load and execute previously compiled programs:

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

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

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

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

    Ok(())
}

Network Configuration from TOML

Use a configuration file for network settings:

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

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

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

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

    Ok(())
}

Error Handling

Comprehensive error handling example:

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

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

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

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

    runtime.program().execute_local()
}

Using the CLI Template

The easiest way to get started:

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

# Build and run
cargo run

The generated project includes a complete example with:

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