Arcis is a Rust framework for writing MPC circuits on Solana. This page is a quick reference —for conceptual understanding, see Thinking in MPC .
Use this page when you need quick syntax lookup while coding.
Quick Reference: Limitations
Category Supported Not Supported Control Flow if, if/else, else if, for loopswhile, loop, break, continue, match, if let, early returnTypes Integers, floats, arrays, tuples, structs Vec, String, HashMap, enumsFunctions Helpers, closures, generics, traits Recursion, async/await Operations Arithmetic, comparisons, right shift (const) Left shift, right shift (variable)
Why? MPC circuits must have fixed structure. See Thinking in MPC for the full explanation.
Basic Structure
use arcis ::* ;
#[encrypted]
mod my_circuit {
use arcis ::* ;
#[instruction]
pub fn add ( a : u8 , b : u8 ) -> u16 {
a as u16 + b as u16
}
}
#[encrypted] marks modules containing MPC circuits
#[instruction] marks entry points callable from Solana
Working with Encrypted Data
#[instruction]
pub fn process ( input : Enc < Shared , u64 >) -> Enc < Shared , u64 > {
let value = input . to_arcis (); // Encrypted → secret shares
let result = value * 2 + 10 ; // Compute on shares
input . owner . from_arcis ( result ) // Secret shares → encrypted
}
Owner Who Can Decrypt Enc<Shared, T>Client AND MXE Enc<Mxe, T>MXE only
Types
// Integers
let x : u8 = 255 ;
let y : i64 = - 1000 ;
let z : u128 = 10000 ;
// Floats (emulated fixed-point)
let pi : f64 = 3.14159 ;
// Arrays (fixed-size only)
let arr : [ u8 ; 10 ] = [ 0 ; 10 ];
// Tuples and structs
let pair : ( u8 , u16 ) = ( 1 , 2 );
#[derive( Copy , Clone )]
struct Point { x : u16 , y : u16 }
See Types for complete reference.
Control Flow
// if/else: when condition is not a compile-time constant, both branches execute
let result = if condition { a } else { b };
// if without else (for side effects)
if should_update {
counter += 1 ;
}
// else if chains work normally
let category = if value < 10 {
0
} else if value < 100 {
1
} else {
2
};
// for loops: fixed iteration count required
for i in 0 .. 10 {
process ( arr [ i ]);
}
Functions
// Helper function
fn helper ( a : u8 , b : u8 ) -> u16 {
a as u16 + b as u16
}
// Closures
let double = | x : u8 | x * 2 ;
// Generics
fn set_zero < T : ArcisType + Copy >( a : & mut T ) {
* a = make_zero ( * a );
}
See Operations for generics and traits.
Arrays
let arr : [ u8 ; 10 ] = [ 0 ; 10 ];
// Constant index: O(1)
let x = arr [ 5 ];
// Secret index: O(n)
let y = arr [ secret_idx ];
// Methods
arr . swap ( 0 , 1 );
arr . reverse ();
arr . fill ( 42 );
arr . sort (); // O(n·log²(n)·bit_size)
Iterators
// Basic iteration
for val in arr . iter () {
sum += * val ;
}
// Chaining
arr . iter () . map ( | x | * x * 2 ) . sum ()
See Operations for complete iterator support. Note: .filter() is not supported.
Encryption Patterns
// Shared: client + MXE can decrypt
fn process ( input : Enc < Shared , u64 >) -> Enc < Shared , u64 >
// MXE-owned: only MXE can decrypt
fn process_state ( state : Enc < Mxe , GameState >) -> Enc < Mxe , GameState >
// Reveal (use carefully)
let plain = secret . reveal ();
// Create MXE-owned data
let mxe_data = Mxe :: get () . from_arcis ( value );
// EncData output (smaller callback payload)
fn verify ( a : Enc < Shared , T >, observer : Shared ) -> EncData < bool > {
observer . from_arcis ( result ) . data
}
See Input/Output for details. For EncData usage, see Types .
Randomness
let coin = ArcisRNG :: bool ();
let num = ArcisRNG :: gen_integer_from_width ( 64 );
let uniform = ArcisRNG :: gen_uniform :: <[ u8 ; 32 ]>();
ArcisRNG :: shuffle ( & mut arr );
let ( val , ok ) = ArcisRNG :: gen_integer_in_range ( 1 , 100 , 24 );
See Primitives for complete RNG reference.
Cryptography
// Hashing
let hash = SHA3_256 :: new () . digest ( & data ) . reveal ();
// Signature verification
let valid = vk . verify ( & message , & signature ) . reveal ();
// Key generation
let sk = SecretKey :: new_rand ();
let vk = VerifyingKey :: from_secret_key ( & sk );
// MXE signing
let sig = MXESigningKey :: sign ( & message ) . reveal ();
See Primitives for complete crypto reference.
Data Packing
// Pack for efficient storage
let packed = Pack :: new ( data );
// Unpack to use
let data : [ u8 ; 64 ] = packed . unpack ();
See Primitives for details.
Debugging
println! ( "value = {}" , x );
debug_assert! ( x > 0 , "x must be positive" );
See Best Practices for debugging strategies.
Testing
#[cfg(test)]
mod tests {
#[test]
fn test_helper () {
// Only non-#[instruction] functions can be unit tested
assert_eq! ( helper ( 1 , 2 ), 3 );
}
}
See Best Practices for testing strategies.
What’s Next?
Ready to build? Start here:
Hello World Build your first Arcis circuit step-by-step.
Solana Integration Invoke circuits from your Solana program.
JavaScript Client Call circuits from TypeScript.