Skip to main content
Arcis provides built-in primitives for randomness, cryptography, and efficient data storage. These operations are implemented as optimized MPC circuits.

Random number generation

The ArcisRNG struct provides access to randomness within MPC circuits. All random values are generated within the MPC context.

Basic usage

The width parameter in gen_integer_from_width must be known at compile time.

Public vs secret random integers

Use gen_public_integer_from_width when you need randomness that does not need to stay secret within the MPC computation (for example, nonce generation). The value is visible to Arx nodes during execution but is not automatically included in the circuit output; you still control what gets returned.

Range-based generation

To generate integers within a specific range, use gen_integer_in_range:
The function uses rejection sampling. Each attempt has >50% success probability, so n_attempts=24 gives a failure probability below 2^-24.
The n_attempts parameter must be known at compile time.

Shuffling

Shuffle arrays in-place with cryptographic uniformity:
Complexity: O(n·log³(n) + n·log²(n)·sizeof(T))

What works and what doesn’t

Cryptographic operations

SHA3 hashing

Arcis provides SHA3-256 and SHA3-512 hash functions:
Arcis uses SHA3 (Keccak) rather than SHA-2/SHA-512 because SHA3 has a more efficient circuit structure for MPC evaluation.

Ed25519 signatures

Arcis provides Ed25519 signature operations using SHA3-512 internally (ArcisEd25519).

Signature verification

Key generation

Only the public verifying key is revealed. The secret key is never revealed in plaintext; it exists only as secret shares distributed across Arx nodes. Arcium uses a dishonest majority model: privacy is maintained as long as at least one node remains honest, even if every other node colludes.

MXE cluster signing

Sign messages using the MXE cluster’s collective key:

Public key operations

Work with X25519 public keys:
For advanced use, work with the Montgomery X coordinate directly:
Coordinate extraction is for advanced cryptographic operations such as:
  • Custom ECDH key exchange implementations
  • Key derivation from shared secrets
  • Interoperability with external systems that work with raw Curve25519 coordinates
  • Zero-knowledge proof inputs that require field elements
Most applications should use from_base58() or from_uint8() for standard public key handling.
About .reveal(): Revealing cryptographic keys or signatures makes them public to all Arx nodes. Only reveal data that is intended to be public output. For internal computations, keep values in secret-shared form.

Reveal constraints

Learn where .reveal() and .from_arcis() can be called.

BaseField25519 operations

BaseField25519 (integers modulo 2^255 - 19) is the native field element for Arcis MPC circuits. Use it for raw field arithmetic without truncation or overflow: cryptographic primitives, Pedersen commitments, curve coordinate work. For bounded arithmetic, comparison-heavy logic, or when you need bitwise operations and division operators, use regular integers (u8..u128) instead.

Construction

All from_* functions work both in plaintext Rust and inside #[encrypted] blocks.

Extraction (unchecked)

These methods are unchecked: if the field element value exceeds the target type’s range, the result is undefined or otherwise incorrect. The circuit will not error; it will silently produce incorrect output.

Arithmetic

All operations wrap modulo 2^255 - 19 (not at integer type boundaries).

Comparisons

==, !=, <, <=, >, >= all produce bool.
Comparisons are unsigned: the field element is treated as a number in [0, p-1]. This means BaseField25519::from_i8(-1) wraps to p - 1 and compares greater than BaseField25519::from_u8(0).

Serialization

Division methods

euclidean_division will panic at runtime if the divisor is zero. Use field_division if you need safe handling of zero divisors.

Differences from regular integers

BaseField25519 is not an integer type. The following operations available on u8..u128 are not supported:
  • No / or % operators: use .field_division() or .euclidean_division() instead
  • No >>, << (shift operators are not supported; &, |, ^ are booleans-only across all types)
  • No MIN, MAX, BITS constants
  • No .min(), .max(), .abs() and no .sort() on arrays of field elements
  • No .to_be_bytes(): only .to_le_bytes()
  • No as casts: use from_* / to_*_unchecked methods
Pack<BaseField25519> provides no compression: each value already occupies one full field element. Only use Pack with smaller types like [u8; N].

Data packing

The Pack<T> type provides bit-level compression for onchain storage efficiency.

Why packing matters

In Arcis, all values are stored as field elements (~255 bits / 32 bytes each). Without packing:
  • A single u8 (8 bits) uses one full field element
  • [u8; 256] uses 256 field elements
With packing, multiple small values are combined into fewer field elements: The math:
  • [u8; 256] = 256 bytes total
  • Each field element packs ~26 bytes (208 usable bits)
  • Packed: ⌈256 / 26⌉ = 10 field elements
  • Compression: 256 → 10 = ~26x fewer field elements
Without packing, each u8 would use a full field element (256 elements total). This significantly reduces onchain storage costs and transaction sizes.

When to use Pack

  • Large arrays of small integers ([u8; N], [u16; N])
  • Data that needs to be stored onchain
  • Input/output parameters approaching transaction size limits

Basic usage

Trade-off: Packing/unpacking has compute cost. Use Pack<T> when storage savings outweigh the computation overhead, typically for arrays of 32+ small integers.

Client-side Packing

How to use generated packers with encrypted inputs in TypeScript.

Simple example

These basic patterns cover most Pack<T> use cases. The “Practical Example” below shows advanced usage with encrypted types.

Practical example

Pack with crypto types

Cryptographic types like VerifyingKey are often passed as Pack<VerifyingKey>:

Machine learning

Arcis includes basic ML primitives for privacy-preserving inference.

Logistic regression

Linear regression

Available ML functions

ML models support up to 100 features (MAX_FEATURES = 100). For larger models, consider feature selection or dimensionality reduction.

Summary

What’s next?

Best practices

Performance optimization, debugging, and testing strategies.

Operations

Full function and method reference.