Complete reference for supported operations, expressions, and patterns in Arcis MPC circuits
Arcis supports many of Rust’s native operations and extends them for encrypted data, allowing you to write private computations using familiar Rust syntax. See the tables below for a detailed list of supported and unsupported operations.
Use this page when you need to check if a specific operation is supported in Arcis circuits.
Cannot be supported as the number of iterations is not known.
Why both branches count: In MPC, both if and else branches are always evaluated—the condition only selects which result to use. This ensures the execution pattern does not leak information about the condition value. See Thinking in MPC for details.
ArcisRNG::gen_uniform::<T>() to generate a uniform value of type T (bool, integer, or combination). Requires explicit type parameter.
ArcisRNG::gen_integer_from_width(width: usize) -> u128. Generates a secret integer between 0 and 2^width - 1 included.
ArcisRNG::gen_public_integer_from_width(width: usize) -> u128. Generates a public integer between 0 and 2^width - 1 included.
ArcisRNG::gen_integer_in_range(min: u128, max: u128, n_attempts: usize) -> (u128, bool). Generates a random integer in [min, max] using rejection sampling. n_attempts must be compile-time known. Returns (result, success) where success=false indicates all attempts were rejected. With n_attempts=24, failure probability is <2^-24.
ArcisRNG::shuffle(slice) on slices. Complexity is in O(n*log³(n) + n*log²(n)*sizeof(T)).
Mxe::get() to be able to create MXE-owned secret data.
Shared::new(arcis_public_key) to share private data with arcis_public_key.
ArcisX25519Pubkey::from_base58(base58_byte_string) to create a public key from a base58-encoded address.
ArcisX25519Pubkey::from_uint8(u8_byte_slice) to create a public key from a Uint8 array.
SolanaPublicKey::from_serialized(value) to create a Solana public key from serialized form.
SolanaPublicKey::from_base58(byte_string) to create a Solana public key from base58.
ArcisMath::sigmoid(x) for the sigmoid activation function.
LogisticRegression::new(coef, intercept) for logistic regression models.
LinearRegression::new(coef, intercept) for linear regression models.
Pack::new(value) to bit-pack data for onchain storage (multiple small values fit into fewer field elements).
ArcisX25519Pubkey::new_from_x(x: BaseField) to create a public key from its Curve25519 Montgomery X-coordinate.
ArcisX25519Pubkey::to_x() to extract the Montgomery X-coordinate from a public key.
The following macros are supported to help debug your Rust code:
debug_assert!, debug_assert_ne!, debug_assert_eq!. They do not change instruction behavior and are only useful for debugging your Rust code.
eprint!, eprintln!, print!, println!. They do not change instruction behavior and are only useful for debugging your Rust code.
arcis_static_panic!(message) to fail compilation when the branch is reached. Useful for enforcing constraints that must be known before circuit generation.
Example usage:
Copy
Ask AI
const ARRAY_LEN: usize = 3; // Change to 1 and the example will not compile.fn second_element(arr: &[u8]) -> u8 { if arr.len() < 2 { arcis_static_panic!("Array must have at least 2 elements"); } arr[1]}#[instruction]fn reveal_second_element(input: Enc<Shared, Pack<[u8; ARRAY_LEN]>>) -> u8 { let array = input.to_arcis().unpack(); second_element(&array).reveal()}
arcis_static_panic! triggers at compile time when the Arcis compiler evaluates the branch. Try changing ARRAY_LEN to 1 above—the compile error demonstrates how this macro enforces constraints that must be validated before circuit generation.
#[instruction]fn iterator_examples(arr: [u8; 10]) -> u16 { // Basic iteration let mut sum = 0u16; for val in arr.iter() { sum += *val as u16; } // Method chaining arr.iter() .map(|x| *x as u16) .map(|x| x * 2) .sum()}
Since .filter() is not supported (it produces variable-length output), use a manual loop with conditionals:
Copy
Ask AI
// ✗ Not supportedarr.iter().filter(|x| **x > threshold).sum()// ✓ Manual filter pattern#[instruction]fn filter_sum(arr: [u8; 10], threshold: u8) -> u16 { let mut sum = 0u16; for val in arr.iter() { if *val > threshold { sum += *val as u16; } } sum}
This pattern checks all elements but only accumulates those meeting the condition—same result, fixed execution structure.