Skip to content

Conversation

@Mikerah
Copy link
Contributor

@Mikerah Mikerah commented Jan 8, 2026

Summary

Consolidated Python SDK implementation with:

Changes

New High-Level API

  • Stoffel entry point with compile(), compile_file(), load() methods
  • StoffelBuilder fluent builder for MPC configuration
  • StoffelRuntime thin wrapper holding program + config
  • MPCConfig dataclass matching Rust SDK
  • ProtocolType, ShareType, OptimizationLevel enums
  • Unified error hierarchy (StoffelError, CompilationError, ConfigurationError, etc.)

FFI Bindings (ported from PRs #3 and #4)

  • stoffel/native/vm.py: NativeVM with load() method
  • stoffel/native/compiler.py: stoffel_compile_to_binary() FFI
  • stoffel/native/mpc.py: Complete MPC FFI with U256, FieldKind, NativeShareManager
  • stoffel/_core.py: Working execute_local() implementation

MPCaaS Server (new)

  • stoffel/mpcaas/server.py: HoneyBadger MPC server with QUIC networking
  • stoffel/native/network.py: QUIC network FFI bindings with party ID support
  • stoffel/native/quic_ffi.py: Low-level QUIC FFI including new_quic_network_with_party_id()

MPC Configuration Validation

  • Validates HoneyBadger constraint: n >= 3t + 1
  • Validates ROBUST shares required for HoneyBadger

Supersedes

Dependencies

  • Requires mpc-protocols PR #65 for new_quic_network_with_party_id() FFI function

Test plan

  • 39 unit tests for builder pattern and config validation
  • All existing tests pass
  • Manual verification with native libraries
  • Integration test with HoneyBadger MPC preprocessing

Usage

from stoffel import Stoffel, ProtocolType, ShareType

runtime = Stoffel.compile("fn main() { return 42; }") \
    .parties(5) \
    .threshold(1) \
    .protocol(ProtocolType.HONEYBADGER) \
    .share_type(ShareType.ROBUST) \
    .build()

print(runtime.program)      # bytes
print(runtime.mpc_config)   # MPCConfig(parties=5, threshold=1, ...)

🤖 Generated with Claude Code

Mikerah and others added 6 commits January 7, 2026 20:49
This commit adds the foundation for MPCaaS (MPC as a Service) support
in the Python SDK, matching the Rust SDK's client-server architecture.

New modules:
- stoffel/native/: Core FFI infrastructure
  - _lib_loader.py: Centralized platform-specific library loading
  - types.py: ctypes structures (U256, ByteSlice, shares, etc.)
  - errors.py: Error code mappings and exception classes
  - quic_ffi.py: Raw ctypes bindings for QUIC networking
  - network.py: Async QUICNetwork wrapper with ThreadPoolExecutor
  - hb_client_ffi.py: HoneyBadger MPC client FFI bindings

- stoffel/mpcaas/: MPCaaS protocol layer
  - protocol.py: Wire-compatible message serialization (bincode-style)
  - client.py: StoffelClient with builder pattern
  - server.py: StoffelServer with builder pattern

- examples/honeybadger_mpc_demo.py: E2E demo matching Rust SDK

The implementation uses ctypes FFI bindings to native Rust libraries
for a minimal dependency footprint (security-first approach).

Note: This is initial scaffolding. Full FFI integration requires
native libraries to be built and some FFI exports may need additions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements Phase 1 of parallel development plan (non-STO-356 blocked work):

Core Builder API:
- Add Stoffel entry point with compile(), compile_file(), load() methods
- Add StoffelBuilder with fluent API for MPC configuration
- Add StoffelRuntime thin wrapper holding program + MPCConfig
- Add ProtocolType, ShareType, OptimizationLevel enums
- Add unified error hierarchy matching Rust SDK

FFI Wrappers:
- Add vm_ffi.py for StoffelVM native bindings
- Add compiler_ffi.py for StoffelLang compiler bindings
- Add share_ffi.py for secret sharing FFI

Enhanced Program Class:
- Add bytecode() method to get raw bytes
- Add save() method to write bytecode to file
- Add list_functions() and execute_function() methods

MPC Configuration:
- Validate HoneyBadger constraint: n >= 3t + 1
- Validate ROBUST shares required for HoneyBadger

Tests:
- Add 39 unit tests for builder pattern and config validation

Usage:
  from stoffel import Stoffel, ProtocolType

  runtime = Stoffel.compile(source) \
      .parties(5) \
      .threshold(1) \
      .build()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Consolidates FFI implementations from closed PRs:
- PR #3: VM bytecode loading (stoffel_load_bytecode, NativeVM.load())
- PR #4: MPC secret sharing (U256, FieldKind, NativeShareManager)

Files added:
- stoffel/_core.py: Working execute_local() implementation
- stoffel/native/vm.py: NativeVM with load() method
- stoffel/native/compiler.py: stoffel_compile_to_binary() FFI
- stoffel/native/mpc.py: Complete MPC FFI with U256/FieldKind

Closes: PR #3 (feature/vm-bytecode-execution)
Closes: PR #4 (feature/mpc-protocols-ffi)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add VMWithMPC wrapper for executing bytecode with real MPC operations
- Add HoneyBadger engine FFI bindings (hb_engine_ffi.py)
- Add network FFI bindings (network_ffi.py)
- Update server to use VMWithMPC for MPC computation
- Add TLS initialization guard to prevent rustls panic on multiple calls
- Export new MPC-VM integration classes from mpcaas module

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add FFI bindings for mpc-protocols' extract_quic_network() function which
converts NetworkOpaque to a raw Arc<QuicNetworkManager> pointer that
StoffelVM's hb_engine_new() expects.

Changes:
- quic_ffi.py: Add extract_quic_network() and free_raw_quic_network() bindings
- network.py: Update get_hb_network() to return StoffelVM-compatible pointer
- server.py: Re-enable HoneyBadger engine creation (was disabled for debugging)
- hb_engine_ffi.py: Improve pointer handling for network argument

This fixes the segfault caused by FFI type mismatch between mpc-protocols
(NetworkOpaque wrapping GenericNetwork) and StoffelVM (expecting raw Arc).

Requires: mpc-protocols PR #65 (feat/extract-quic-network-ffi branch)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add party_id parameter to QUICNetwork for proper MPC connection mapping.
This fixes the "PREPROCESSING_FAILED" error in HoneyBadger preprocessing.

Root cause:
- new_quic_network() created random UUID-based node_ids
- HoneyBadger expected sequential party IDs (0, 1, 2, etc.)
- Network::send(recipient) couldn't find connections by party ID

Changes:
- quic_ffi.py: Add binding for new_quic_network_with_party_id FFI
- network.py: Add party_id parameter to QUICNetwork
- server.py: Pass party_id when creating network

Test results:
- Before: Immediate "PREPROCESSING_FAILED" error
- After: Preprocessing runs (no immediate failure)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants