Quick summary
Works:if/else, if let, match, for loops, arithmetic, comparisons, iterators (except filter)
Doesn’t work: while, loop, break, continue, return, let ... else, .filter()
See tables below for full details.
Table of contents
Expression support
Why branches count: In MPC, both sides of non-constant conditional execution are evaluated, including
if/else branches and non-constant match arms. 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.Binary expressions
User-defined binary operations are currently unsupported.BaseField25519 does not support /, %, >>, or <<. &, |, ^ are booleans-only across all types. Use .field_division() or .euclidean_division() for division on field elements. See BaseField25519 Operations.Cast expressions
a as MyType is only supported:
Function calls
The following function calls are supported:- user-defined function calls (without recursion)
ArcisRNG::bool()to generate a boolean.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_attemptsmust be compile-time known. Returns(result, success)wheresuccess=falseindicates all attempts were rejected. Withn_attempts=24, failure probability is<2^-24.ArcisRNG::shuffle(slice)on slices. Complexity is inO(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 witharcis_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: BaseField25519)to create a public key from its Curve25519 Montgomery X-coordinate.ArcisX25519Pubkey::to_x() -> BaseField25519to extract the Montgomery X-coordinate from a public key.BaseField25519::from_u8(x)…BaseField25519::from_u128(x)to convert unsigned integers to field elements. Signed variants (from_i8…from_i128) andfrom_bool,from_usize,from_isizealso available.BaseField25519::power_of_two(exp)to compute2^expas a field element.
Literal expressions
Macros
The following macros are supported:debug_assert!,debug_assert_ne!,debug_assert_eq!to assert conditions during debugging. They do not change instruction behavior.eprint!,eprintln!,print!,println!to print debug output. They do not change instruction behavior.matches!(expr, pattern)to test a pattern and returnbool. See Pattern support.arcis_static_panic!(message)to fail compilation when the branch is reached. Useful for enforcing constraints that must be known before circuit generation.include_bytes!("file_path")to include raw bytes from a file in Arcis circuits.include!("file_path")to include a file in item position (not expression position).assert_current_module!(crate::path::to::module)to enablecrate::absolute paths within the current module. Place at the top of any module that needs to reference items via absolute paths.encrypted_mod!("path/to/module.rs")orencrypted_mod!("path/to/module.rs", alias_name)to use another file as a module within an#[encrypted]module. The target file must use the#[encrypted_library]attribute. Items are accessible via the filename stem (or alias) as a namespace, e.g.,module_name::ITEM.
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.Method calls
The following method calls are supported:- user-defined method calls (with generics but without recursion)
.clone()on allCloneobjects..len(),.is_empty(),.swap(a, b),.fill(value),.reverse(),.iter(),.iter_mut(),.into_iter(),.windows(width),.copy_from_slice(src),.clone_from_slice(src),.split_at(mid),.split_at_mut(mid),.rotate_left(mid),.rotate_right(mid),.contains(item),.starts_with(needle),.ends_with(needle),.as_slice(),.as_mut_slice()on arrays and slices..first(),.first_mut(),.last(),.last_mut(),.get(index),.get_mut(index),.split_first(),.split_first_mut(),.split_last(),.split_last_mut(),.first_chunk::<N>(),.first_chunk_mut::<N>(),.last_chunk::<N>(),.last_chunk_mut::<N>(),.split_first_chunk::<N>(),.split_first_chunk_mut::<N>(),.split_last_chunk::<N>(),.split_last_chunk_mut::<N>()on arrays and slices. These returnOption..as_array::<N>(),.as_mut_array::<N>()on slices (requires Rust 1.93+). These returnOption..map(f),.each_ref(),.each_mut()on arrays..sort()on arrays of integers. Complexity is inO(n*log²(n)*bit_size)..enumerate(),.chain(other),.cloned(),.copied(),.count(),.rev(),.zip(other),.map(func),.for_each(func),.fold(init, func),.sum(),.product(),.collect::<Box<[_]>>()on iterators..take(n),.skip(n),.step_by(n)on iterators whennis compile-time known..reveal()if not inside a conditionally executed block (if/else, non-constantmatcharm, or guard).to_arcis()onEncs.from_arcis(x)onOwners (objects of typesMxeorShared) if not inside a conditionally executed block (if/else, non-constantmatcharm, or guard).abs(),.min(x),.max(x)on integers and floats.abs_diff(other),.is_positive(),.is_negative(),.div_ceil(other)on integers.to_le_bytes(),.to_be_bytes(),.wrapping_add(rhs),.wrapping_sub(rhs),.wrapping_mul(rhs)on typed integers (does not work on integers whose type the interpreter does not know).exp(),.exp2(),.ln(),.log2(),.sqrt()on floats..set(val),.swap(other),.update(f),.replace(val),.into_inner(),.get(),.get_mut()onCell..unpack()onPack<T>to extract the original value from packed storage.Option<T>combinators:.is_some(),.is_none(),.is_some_and(f),.is_none_or(f),.unwrap(),.unwrap_or(default),.unwrap_or_else(f),.map(f),.map_or(default, f),.map_or_else(default_f, f),.inspect(f),.filter(predicate),.and(other),.and_then(f),.or(other),.or_else(f),.xor(other),.zip(other),.unzip(),.flatten(),.copied(),.cloned(),.take(),.take_if(predicate),.replace(value),.insert(value),.get_or_insert(value),.get_or_insert_with(f)..to_arcis_with_pubkey_and_nonce(pubkey, nonce)onEncData<T>to decrypt when the key is shared across inputs (avoids duplicate decryption gates). See EncData for details..dataonEnc<Owner, T>to extract only theEncData<T>ciphertext for smaller callback payloads..safe_inverse()onBaseField25519to get the field inverse (returns 0 for inverse of 0)..field_division(divisor)onBaseField25519for field division (returns 0 for division by 0)..euclidean_division(divisor)onBaseField25519for signed Euclidean division (panics on division by 0)..to_u8_unchecked()….to_u128_unchecked()onBaseField25519to extract as unsigned int. Silently produces incorrect results if value exceeds target range. Signed variants (to_i8_unchecked…to_i128_unchecked) andto_bool_uncheckedalso available.
Paths
The following paths are supported:IntType::BITS,IntType::MINandIntType::MAXwhereIntTypeis an integer type.- Paths to user-defined constants, functions and structs, as long as they are inside the
#[encrypted]area. Bothsuper::paths andcrate::paths (whenassert_current_module!is declared) are supported. std::mem::replaceandstd::mem::swapBox::leak,Box::new,Cell::new,Cell::from_mut
Code organization with modules
Arcis supports nested modules,super:: parent references, crate:: absolute paths, and multi-file projects. #[instruction] functions can be placed at any module depth, not just at the top level.
Submodules with super:: and crate:: paths:
encrypted_mod!:
Each file imported via
encrypted_mod! must use #[encrypted_library] (not #[encrypted]). Items are accessible through the filename stem as a namespace (e.g., helpers::Config), or you can provide an alias: encrypted_mod!("helpers.rs", utils) makes items accessible as utils::Config.Item support
¹ Forbidden trait implementations: You cannot manually implement
Drop, Deref, AsRef, AsMut, From, Into, TryFrom, TryInto, PartialEq, Eq, PartialOrd, Ord, Clone, ToOwned, ToString, Iterator, IntoIterator, DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, Fn, FnMut, FnOnce, Future, IntoFuture, AsyncFn, AsyncFnMut, or AsyncFnOnce.Why? These traits have special runtime semantics (drop ordering, lazy evaluation, dynamic dispatch) that cannot be correctly translated to fixed MPC circuits. The Arcis compiler provides built-in implementations that work within MPC constraints.Use #[derive(...)] for Clone, PartialEq, Default, etc., which generates MPC-compatible implementations. Default also supports a manual impl Default for T.Pattern support
The following patterns are supported in function arguments,let statements, if let conditions, matches! calls, and match expressions:
- simple idents:
let ident = ...; - mutable idents:
let mut ident = ...; - ref idents:
let ref ident = ...; - mutable ref idents:
let ref mut ident = ...; - parentheses around a supported pattern:
let (...) = ...; - reference of a supported pattern:
let &... = ...; - array of supported patterns:
let [...] = ...; - struct of supported patterns:
let MyStruct { ... } = ...; - tuple of supported patterns:
let (...) = ...; - tuple struct of supported patterns:
let MyStruct(...) = ...; - type pattern of a supported pattern:
let ...: ty = ...; - wild pattern:
let _ = ...;
| patterns are supported only in if let, matches!, and match; they cannot be used on a match arm that also has a guard. The .. pattern is only supported inside struct patterns with named fields, e.g. MyStruct { x: 0, .. }.
Literal, range, and path-constant patterns are only supported in if let, matches!, and match. Path constants must use a path such as module::MY_CONST; bare const identifiers are not supported as patterns.
Pattern matching
Arcis supportsmatch expressions, if let (including let chains), and the matches! macro for branching on patterns. Patterns can be literals, ranges, path constants like module::MY_CONST, OR-patterns, tuples, structs (with .. rest), arrays/slices, references, bindings, and wildcards. Match arms can use if-guards, except an arm cannot combine a guard with an OR-pattern.
let ... else remains unsupported. In match, guards are supported, but an arm cannot combine a guard with an OR-pattern.match expressions
if let and let chains
Let chains (
if let ... && let ... && ...) require Rust edition 2024. The default arcium init scaffold sets edition = "2021" in encrypted-ixs/Cargo.toml. Bump it to edition = "2024" to use this syntax.matches! macro
matches! returns a bool and supports the same pattern surface:
Slice patterns
Fixed-size arrays viewed as slices can be matched with arms of different lengths:Item shadowing of a
let binding is rejected. Defining fn f() or const F: _ after let f = ... (or let F = ...) errors at compile time with “Cannot have an item with the same name as a variable in scope.” let shadowing another let is still allowed.Generics
Arcis supports Rust generics with some constraints. Generic types must be known at compile time. Runtime polymorphism is not supported.Generic functions
Generic structs
Custom traits
Generic constraints
Iterators
Most iterator methods work in Arcis, with the notable exception of.filter().
Supported iterator methods
Complete iterator support
Filter alternative
Since.filter() is not supported (it produces variable-length output), use a manual loop with conditionals:
What’s next?
Primitives
RNG, cryptography, and data packing operations.
Best practices
Performance tips, debugging, and testing strategies.