All articles
solanaarciummpcprivacy

Arcium: MPC for Solana — compute over encrypted data, on-chain

Arcium runs Multi-Party Computation networks that compute over encrypted inputs without ever revealing them. Here's the integration model with Solana programs.

Arcium is a Multi-Party Computation (MPC) network that integrates with Solana programs. Where ZK rollups prove a computation happened correctly, MPC lets a network of nodes jointly perform a computation over inputs none of them can see individually. For Solana, this means on-chain primitives where the data stays private from everyone — including the Arcium nodes themselves.

The model

Three actors:

  • Users / programs. Submit encrypted inputs to a computation.
  • Arcium nodes (cluster). Hold pieces of every encrypted input. None of them can reconstruct the input alone (the encryption uses MPC secret-sharing). They jointly evaluate the agreed circuit and publish a result.
  • Arcium Solana program. Mediates the request, stores the encrypted inputs as on-chain accounts, accepts the jointly-signed result, and forwards it to your program via callback CPI.

The lifecycle of a computation

text
1. Your program submits a computation request to Arcium
   (computation_id + encrypted inputs as ciphertext accounts)
   ↓
2. Arcium nodes pick up the request, each holds shares of every input
   ↓
3. Nodes jointly run the circuit defined by computation_id
   (the circuit is registered ahead of time as bytecode)
   ↓
4. Nodes publish the encrypted output and a threshold signature
   proving they ran the right circuit on the right inputs
   ↓
5. The Arcium Solana program verifies the signature, decrypts the
   output (or hands the still-encrypted result back to a specific
   recipient who holds the decryption key)
   ↓
6. Arcium CPIs into your program's callback with the result

The circuit definition

Computations are written in a DSL called Arcis (Rust-flavoured). The compiler turns them into MPC circuits the node network can execute.

rust
// Arcis circuit — runs in the MPC network, inputs stay encrypted
#[mpc_circuit]
pub fn sealed_auction(
    bids: Vec<EncryptedU64>,    // each node has a share of each bid
    bidders: Vec<EncryptedPubkey>,
) -> (EncryptedPubkey, EncryptedU64) {
    let (winner_idx, winner_bid) = max_by_value(&bids)?;
    (bidders[winner_idx], winner_bid)
}

The bids are never visible to any node — the network jointly evaluates the max function over the secret-shared values. Only the winner's identity + winning bid amount is revealed (and even those can be returned encrypted if the design calls for it).

Use cases on Solana

  • Sealed-bid auctions. NFT mints, governance token launches. Bidders submit encrypted bids; the auction-clearing happens in MPC; only the winners are revealed.
  • Dark pools. Order matching over hidden orders — your buy/sell intent is never visible to other participants or to the protocol operators.
  • Private DAO voting. Vote secrecy with on-chain verifiability — only the tally is revealed, never who voted which way.
  • Private credit scoring. A lender can decide whether to extend credit based on a borrower's aggregated on-chain history without ever seeing the raw transactions.
  • AI inference over private inputs. Run a model on a user's data without the model operator ever seeing the data.

MPC vs ZK — when to pick each

text
                  MPC (Arcium)                ZK proofs
─────────────────────────────────────────────────────────────────────
Who learns what?  Nothing — output encrypted   Verifier learns the
                  to recipient                  statement, not witness
Trust model       Threshold of MPC nodes       Math (trustless)
Compute cost      Distributed; cheap inputs    Expensive proving step
                  expensive interaction
Setup ceremony    Per-circuit precomputation   Per-circuit setup
                                                (sometimes trusted)
Best for          Multi-party shared inputs    Single-prover statements

MPC wins when multiple parties contribute private inputs to a shared computation. ZK wins when one party wants to prove something about their own private data without revealing it.

The callback pattern from your program

rust
use arcium_anchor::queue_computation;

#[program]
pub mod my_auction {
    use super::*;

    pub fn submit_bid(ctx: Context<SubmitBid>, encrypted_bid: Vec<u8>) -> Result<()> {
        queue_computation(
            ctx.accounts.arcium_pool,
            "sealed_auction",                     // pre-registered circuit id
            vec![encrypted_bid],
            CALLBACK_DISCRIMINATOR,
        )?;
        Ok(())
    }

    // Arcium calls back when the computation finishes
    pub fn handle_auction_result(
        ctx: Context<HandleResult>,
        winner: Pubkey,
        winning_bid: u64,
    ) -> Result<()> {
        ctx.accounts.auction.winner = winner;
        ctx.accounts.auction.final_price = winning_bid;
        Ok(())
    }
}

References

Arcium fills the gap between "all data public on-chain" (default Solana) and "all computation off-chain" (just run a server). It's the right primitive when a computation needs to be on-chain-verifiable but its inputs need to stay private — and it's one of the few production-grade MPC networks integrated with any L1.

Arcium: MPC for Solana — compute over encrypted data, on-chain | devrels.xyz