Skip to main content
Scope: AI-agent-agnostic playbook for building applications with the Stoffel framework. This is not a maintainer guide for compiler, VM, protocol, or release engineering work. Dependency assumption: use current public crates.io releases by default, then the official GitHub repository at a full immutable revision when the needed change is not published. A local checkout is a separate, explicitly requested, nonportable framework-development workflow.

Use when

Use this playbook when an app handles private values, secret shares, client-provided inputs, MPC output delivery, protocol/runtime metadata, or secure algorithm examples.

Goal

Help developers write MPC-oriented Stoffel apps using secret types, Share.*, ClientStore.*, Mpc.*, MpcOutput.*, and related builtins, while preserving runnable local examples. For client-owned private input in a multi-user or networked application, the participant-owned process is the Stoffel MPC client and submits directly to the separately deployed MPC service. The application control plane must not receive or persist participant plaintext. Complete the trust-boundary worksheet in Stoffel Full App Golden Path, then use Stoffel App Network and Off-Chain Integration for the production client path.

Current source of truth

  • crates/stoffel-lang/examples/README.md
  • crates/stoffel-lang/examples/COVERAGE.md
  • crates/stoffel-lang/examples/mpc_*
  • crates/stoffel-lang/examples/bits/secret/*
  • crates/stoffel-lang/examples/matrix/secret/*
  • crates/stoffel-lang/examples/polynomials/secret/*
  • crates/stoffel-lang/examples/number_theory/secret/*
  • crates/stoffel-lang/examples/avss_*
  • crates/stoffel-lang/examples/threshold_signatures/*

Minimal secret app

When run locally through the CLI/SDK, source/file programs returning a secret value may be wrapped/opened by the local execution path so app tests can assert clear outputs. For client-owned private inputs, use ClientStore in the Stoffel program. The CLI flags below inject plaintext into one trusted local harness process for program testing; they do not define the production application-service path:
The first argument to ClientStore.take_share(client_slot, input_index) is the client slot. The second is that client’s ordered input index. Repeating --client-input 0=... appends inputs for slot 0 in order.

Secret values and shares

Common patterns:
Prefer secret T annotations when you know the share’s scalar shape. The secret keyword belongs inside type annotations for parameters, return types, local variables, list elements, and object fields:
Do not use secret as a declaration modifier before def or var. Use var x: secret int64 = ..., not secret var x = .... Use normal arithmetic operators (+, -, *, /) for secret values when the operation fits the value shape. Method/function forms such as Share.add, Share.mul, .add_scalar, and .mul_scalar remain useful when you want to call a specific builtin explicitly. For fixed-point client inputs:
For boolean circuits:

Client input shares

Use ClientStore when participant-owned SDK clients provide private inputs through the coordinator/client path. Each client owns and submits its complete ordered input vector directly; do not place .with_client_input(...), plaintext client fields, or private payload proxies in an application backend:
CLI flags:
Input-file equivalents are documented in Stoffel CLI App Workflow. Treat CLI flags and input files as trusted local fixtures. They prove program semantics, not that a production control plane is outside the plaintext path.

Client outputs

Send share outputs to clients when the runtime advertises that capability:
Many current examples now document --expected-output-clients N in a first-line # run-args: header. Preserve that flag in local runs; without it, output-capable client slots may not be declared in the local runtime.

Runtime metadata

Useful app metadata:
  • Mpc.party_id()
  • Mpc.n_parties()
  • Mpc.threshold()
  • Mpc.instance_id()
  • Mpc.protocol_name()
  • Mpc.curve() / Mpc.field()
  • Mpc.is_ready()
  • Mpc.has_capability(name)
  • Mpc.capabilities()
  • Mpc.rand() / Mpc.rand_int()

Example families to inspect

MPC primitive examples:
  • mpc_share_arithmetic
  • mpc_boolean_circuit
  • mpc_bitwise_share
  • mpc_random_bit
  • mpc_bit_decomposition
  • mpc_secure_comparison
  • mpc_select_minmax
  • mpc_aes128_circuit
  • mpc_client_private_score
  • mpc_client_federated_average
  • mpc_protocol_coordination
  • mpc_share_toolkit
Secure algorithm examples with recent client I/O headers:
  • Comparison and bit algorithms: mpc_range_check, mpc_clamp, mpc_compare_family, mpc_is_zero, mpc_popcount_secret, mpc_msb_log2, mpc_lowest_set_bit, mpc_parity, mpc_bit_reverse_rotate, mpc_sign_extend.
  • Oblivious data access/search: mpc_oblivious_read, mpc_oblivious_write, mpc_mux_tree, mpc_linear_search, mpc_lookup_table, mpc_pattern_match.
  • Arithmetic/number theory: mpc_secure_division, mpc_modulo_secret, mpc_mod_constant, mpc_gcd, mpc_lcm, mpc_reciprocal, mpc_sqrt, mpc_horner_eval, mpc_secret_base_power, mpc_secret_exponentiation, mpc_modexp, mpc_modinv, mpc_transcendental.
  • Sorting/ranking/arrays: mpc_bitonic_sort, mpc_secure_shuffle, mpc_top_k, mpc_rank_order.
Gallery examples:
  • bits/secret/*: private bit/boolean circuits with ClientStore inputs.
  • matrix/secret/*: private matrix/vector and fixed-point examples.
  • polynomials/secret/*: polynomial, interpolation, coding, and private matching examples.
  • number_theory/secret/*: private GCD, modular inverse, CRT, MAC, equality, and Diophantine examples.
Advanced protocol/crypto examples:
  • avss_share_auditor
  • avss_certificate/*
  • threshold_signatures/*

Validation / done criteria

For a secret app source change:
For an example with a # run-args: header, use the exact flags from that header. Example:
Framework validation:

Common pitfalls

  • Do not use clear function arguments when the program expects ClientStore inputs.
  • Do not move client-owned ClientStore values into an application server or SDK server/node builder. Keep private input encoding and submission in each SDK client.
  • Do not reorder repeated --client-input values for the same slot; order is the per-client input index.
  • Do not omit --expected-output-clients for programs that call MpcOutput.send_to_client or Share.send_to_client.
  • Do not reveal intermediate private values in examples unless the algorithm intentionally opens that result.
  • Do not claim protocol behavior from static compilation alone; run local MPC or report the blocker.