arcis-interpreter 0.9.6

Interpreter for MPC circuits written with Arcis framework.
Documentation
## Table of contents

* [Expression support]#expression-support
  * [Binary expressions]#binary-expressions
  * [Casts]#cast-expressions
  * [Functions]#function-calls
  * [Literals]#literal-expressions
  * [Macros]#macros
  * [Methods]#method-calls
  * [Paths]#paths
* [Item support]#item-support
* [Pattern support]#pattern-support
* [Type support]#type-support
* [Arcis Standard Library]#arcis-standard-library
  * [Cryptography (Ed25519)]#cryptography-ed25519
  * [Hash Functions (SHA3)]#hash-functions-sha3
  * [Solana Integration]#solana-integration
  * [Machine Learning]#machine-learning
  * [Math Functions]#math-functions

# Expression support:

| Expression Name   | Example                        | Support         | Comments                                                                 |
|:------------------|:-------------------------------|:----------------|:-------------------------------------------------------------------------|
| Array literal     | `[a, b]`                       | Supported       |                                                                          |
| Assignment        | `a = b;`                       | Supported       |                                                                          |
| Async block       | `async { ... }`                | Unsupported     |                                                                          |
| Await             | `foo().await`                  | Unsupported     |                                                                          |
| Binary expression | `a + b`                        | Partial Support | [See table below]#binary-expressions for supported binary expressions. |
| Block expression  | `{ ... }`                      | Supported       |                                                                          |
| Break             | `break;`                       | Unsupported     |                                                                          |
| Function call     | `f(a, b)`                      | Partial Support | [See table below]#function-calls for supported functions.              |
| Casts             | `a as u16`                     | Partial Support | [See table below]#cast-expressions for supported conversions.          |
| Closures          | `\|a, b \| a + b`              | Supported       |                                                                          |
| Const block       | `const { ... }`                | Supported       |                                                                          | 
| Continue          | `continue;`                    | Unsupported     |                                                                          |
| Field access/set  | `obj.field`                    | Supported       |                                                                          |
| For loop          | `for i in expr { ... }`        | Supported       | Note that `expr` will have its length known at compile-time.             |
| If                | `if cond { ... } else { ... }` | Supported       | Complexity is in O( then_block + else_block).                            | 
| Indexing          | `a[idx]`                       | Supported       | Complexity will be in O(`a.len()`) if `idx` isn't known at compile-time. |
| If let            | `if let Some(x) = ...`         | Unsupported     |                                                                          |
| Literals          | `1u128`                        | Partial Support | [See table below]#literal-expressions for supported literals.          |
| Loops             | `loop { ... }`                 | Unsupported     | Cannot be supported as the number of iterations is not known.            |
| Macros            | `println!("{}", q)`            | Partial Support | [See table below]#macros for supported macros.                         |
| Match             | `match n { ... }`              | Unsupported     |                                                                          |
| Method calls      | `x.foo(a, b)`                  | Partial Support | [See table below]#method-calls for supported methods.                  |
| Parentheses       | `(a + b)`                      | Supported       |                                                                          |
| Paths             | `Foo::bar`                     | Partial Support | [See table below]#paths for supported paths.                           |
| Ranges            | `4..5`                         | Partial Support | Only supported for set and compile-time-known bounds.                    |
| Raw addresses     | `&raw const foo`               | Unsupported     |                                                                          |
| References        | `&mut foo`                     | Supported       |                                                                          |
| Repeat arrays     | `[4u8; 128]`                   | Supported       |                                                                          |
| Return            | `return false;`                | Unsupported     |                                                                          |
| Struct literals   | `MyStruct { a: 12, b }`        | Supported       |                                                                          |
| Try expression    | `this_call_can_err()?;`        | Unsupported     |                                                                          |
| Tuple literal     | `(a, 4, c)`                    | Supported       |                                                                          |
| Unary expressions | `!x`                           | Partial Support | User-defined unary operations are not supported.                         |
| Unsafe            | `unsafe { ... }`               | Unsupported     |                                                                          |
| While loops       | `while x < 64 { ... }`         | Unsupported     | Cannot be supported as the number of iterations is not known.            |

## Binary expressions

Note: user-defined binary operations are currently unsupported.

| Example    | Supported types                            |
|:-----------|:-------------------------------------------|
| `a + b`    | Integers, floats, `BaseField25519`         |
| `a - b`    | Integers, floats, `BaseField25519`         |
| `a * b`    | Integers, floats, `BaseField25519`         |
| `a / b`    | Integers, floats                           |
| `a % b`    | Integers                                   |
| `a && b`   | Booleans                                   |
| `a \|\| b` | Booleans                                   |
| `a ^ b`    | Booleans                                   |
| `a & b`    | Booleans                                   |
| `a \| b`   | Booleans                                   |
| `a << b`   | None                                       |
| `a >> b`   | Integers, if `b` is known at compile time. |
| `a == b`   | All. Use `derive(PartialEq)` for structs.  |
| `a != b`   | All. Use `derive(PartialEq)` for structs.  |
| `a < b`    | Booleans, integers, floats, `BaseField25519` |
| `a <= b`   | Booleans, integers, floats, `BaseField25519` |
| `a >= b`   | Booleans, integers, floats, `BaseField25519` |
| `a > b`    | Booleans, integers, floats, `BaseField25519` |
| `a += b`   | Integers, floats, `BaseField25519`         |
| `a -= b`   | Integers, floats, `BaseField25519`         |
| `a *= b`   | Integers, floats, `BaseField25519`         |
| `a /= b`   | Integers, floats                           |
| `a %= b`   | Integers                                   |
| `a ^= b`   | Booleans                                   |
| `a &= b`   | Booleans                                   |
| `a \|= b`  | Booleans                                   |
| `a <<= b`  | None                                       |
| `a >>= b`  | Integers, if `b` is known at compile time  |

## Cast expressions

`a as MyType` is only supported:

| From Type    | To Type      |
|:-------------|:-------------|
| integer type | integer type |
| `bool`       | integer type |
| integer type | `bool`       |
| `&...&T`     | `&T`         |

## 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 `T`. It works for `T` being `bool`, an integer or any combination (struct, array, tuple) of working types.
* `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) -> (result: u128, success: bool)`. See function doc for more information.
* `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(public_key: ArcisX25519Pubkey)` to share private data with `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.
* `ArcisX25519Pubkey::new_from_x(x: BaseField25519)` to create a public key from its Curve25519 Montgomery X-coordinate (the standard 32-byte X25519 representation).
* `ArcisX25519Pubkey::to_x() -> BaseField25519` to extract the Montgomery X-coordinate from a public key.
* `BaseField25519::from_u8(x)`, `from_u16(x)`, ..., `from_u128(x)`, `from_usize(x)`, `from_i8(x)`, ..., `from_i128(x)`, `from_isize(x)`, `from_bool(x)` to construct a field element from integers or booleans.
* `BaseField25519::power_of_two(exponent)` to compute `2^exponent` as a field element.
* `Pack::new(value: T)` to bit-pack data for on-chain storage (multiple small values fit into fewer field elements).

## Literal expressions

| Example     | Support     |
|:------------|:------------|
| `"foo"`     | Unsupported |
| `b"foo"`    | Supported   |
| `c"foo"`    | Unsupported |
| `b'f'`      | Supported   |
| `'a'`       | Unsupported |
| `1`         | Supported   |
| `1u16`      | Supported   |
| `1f64`      | Supported   |
| `1.0e10f64` | Supported   |
| `true`      | Supported   |

## Macros

The following macros are supported in order to help you 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.
* `include_bytes!("file_path")` to include an array of bytes.
* `include!("file_path")` but only in item position, not in expression position.
* `arcis_static_panic!(message)` to fail compilation when the branch is reached. Useful for enforcing compile-time-known constraints like array length checks.
* `assert_current_module!(crate::...::module_name)` to enable `crate::` paths.
* `encrypted_mod!("path/to/my_module_name.rs")` or `encrypted_mod!("path/to/my_module.rs", my_module_name)` to use another file as a module. The other file needs to look like this:

```
use arcis::*;

#[encrypted_library]
mod arcis_library {
    // Put your content here.

    // Accessible through `my_module_name::MY_CONST`.
    pub const MY_CONST: usize = 67;
}
```

## Method calls

The following method calls are supported:

* user-defined method calls (generics supported, recursion not supported)
* `.clone()` on all `Clone` objects.
* `.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.
* `.map(f)`, `.each_ref()`, `.each_mut()` on arrays
* `.sort()` on arrays of integers. Complexity is in `O(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 when `n` is compile-time known.
* `.reveal()` if not inside a `if` or a `else`
* `.to_arcis()` on `Enc`s
* `.from_arcis(x)` on `Owner`s (objects of types `Mxe` or `Shared`) if not inside a `if` or a `else`
* `.unpack()` on `Pack<T>` to extract the original value from packed storage.
* `.to_arcis_with_pubkey_and_nonce(pubkey, nonce)` on `EncData<T>` to decrypt when the key is shared across inputs (avoids duplicate decryption gates).
* `.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 the interpreter does not know the type)
* `.exp()`, `.exp2()`, `.ln()`, `.log2()`, `.sqrt()` on floats.
* `.set(val)`, `.swap(other)`, `.update(f)`, `.replace(val)`, `.into_inner()`, `.get()`, `.get_mut()` on `Cell`.
* `.safe_inverse()`, `.field_division(divisor)`, `.euclidean_division(divisor)`, `.to_le_bytes()` on `BaseField25519`.
* `.to_u8_unchecked()`, ..., `.to_u128_unchecked()`, `.to_i8_unchecked()`, ..., `.to_i128_unchecked()`, `.to_bool_unchecked()` on `BaseField25519` to extract a value. UB if out of range.

## Paths

The following paths are supported:

* `IntType::BITS`, `IntType::MIN` and `IntType::MAX` where `IntType` is an integer type.
* Paths to user-defined constants, functions and structs, as long as they are inside the `#[encrypted]` area.
* `std::mem::replace` and `std::mem::swap`
* `Box::leak`, `Box::new`, `Cell::new`, `Cell::from_mut`.

# Item support:

| Item Name         | Example                   | Support         | Comments                                                                                                                               |
|:------------------|:--------------------------|:----------------|:---------------------------------------------------------------------------------------------------------------------------------------|
| Constant          | `const MAX: u16 = 65535`  | Supported       |                                                                                                                                        |
| Enum              | `enum MyEnum { ... }`     | Unsupported     |                                                                                                                                        |
| Extern            | `extern ...`              | Unsupported     |                                                                                                                                        |
| Functions         | `fn foo() -> u8 { 0 }`    | Partial Support | Recursive functions are not supported.                                                                                                 |
| Generics          | `fn foo<T>(x: T) -> T`    | Supported       | Generic type params, const params, lifetime params, trait bounds, turbofish syntax, and `impl Trait` in function signatures supported. |
| Impls             | `impl MyType { ... }`     | Partial Support | Trait impls supported. Generic impls with trait bounds supported. `MyType` should not be a reference.                                  |
| Macro Definitions | `macro_rules! ...`        | Unsupported     |                                                                                                                                        |
| Macro Invocations | `println!(...)`           | Partial Support | [See table above]#macros for supported macros.                                                                                       |
| Modules           | `mod my_module { ... }`   | Supported       |                                                                                                                                        |
| Statics           | `static ...`              | Unsupported     |                                                                                                                                        |
| Structs           | `struct MyStruct { ... }` | Supported       |                                                                                                                                        |
| Traits            | `trait MyTrait { ... }`   | Partial Support | Custom traits supported with methods, constants, and associated types. Standard library traits forbidden.¹                             |
| Type Aliases      | `type MyId = usize;`      | Supported       |                                                                                                                                        |
| Union             | `union MyUnion { ... }`   | Unsupported     |                                                                                                                                        |                   
| Use               | `use arcis::*`            | Partial Support | `::*` is not supported except in  `use arcis::*;`. `::self` is not supported.                                                          |

¹ Forbidden traits: Drop, Deref, AsRef, AsMut, Into, From, PartialEq, Eq, Default, PartialOrd, Ord, Clone, Fn, FnMut, FnOnce, ToOwned, ToString, Iterator, Extend, IntoIterator, DoubleEndedIterator, ExactSizeIterator, TryFrom, TryInto, FromIterator, Future, IntoFuture, AsyncFn, AsyncFnOnce, AsyncFnMut.

Allowed derive macros: `Debug`, `Clone`, `Copy`, `PartialEq`, `Eq`.

Allowed attributes: `allow`, `deny`, `expect`, `forbid`, `warn`, `deprecated`, `must_use`, `inline`, `cold`, `doc`, `non_exhaustive`, `deref`.

# Pattern support:

The following patterns are supported in function arguments and `let` statements:

* 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 _ = ...;`

Note: in particular, the `..` pattern is currently unsupported.

# Type support:

The following types are supported:

* `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`
* `f64`, `f32` (Note: these types are emulated by the fixed-point numbers `k*2^-52`, for `k` between `-2^250` and `2^250`.)
* `BaseField25519`, integers modulo 2^255 - 19. 
* tuples of supported types, including `()`
* fixed-length arrays of a supported type
* fixed-length slices
* compile-time known ranges
* (mutable) references to a supported type
* user-defined structs of supported types
* functions (but not as input or output of an encrypted instruction)
* `Box<T>` and `Cell<T>`.
* `ArcisX25519Pubkey`, an Arcis public key wrapper.
* Arcis-defined `Enc`, `Mxe` and `Shared`.
* `Pack<T>`, a wrapper for bit-packing data into fewer field elements for on-chain storage.
* `EncData<T>`, encrypted data without embedded cipher info. Use with `.to_arcis_with_pubkey_and_nonce()` when multiple values share the same key.

In particular, we do not currently support `HashMap`, `Vec`, `String` (we do not support types with a variable `len`).
Constant-size byte strings (like `b"hello_world"`) are supported.

# Arcis Standard Library

The following types and functions from the arcis standard library are available:

## Cryptography (Ed25519)

* `SecretKey` - Ed25519 secret key type for signing
* `SecretKey::new_rand()` to generate a random secret key
* `SecretKey::from_bytes(bytes: [u8; 32])` to create a secret key from raw bytes
* `SigningKey` - Wrapper around `SecretKey` for signing
* `SigningKey::new(secret_key: SecretKey)` to create a signing key
* `.sign(&message)` on `SigningKey` to produce an `ArcisEd25519Signature`
* `MXESigningKey` - MXE-level signing (signs using the MXE's collective key)
* `MXESigningKey::sign(message)` to sign a message with the MXE key
* `VerifyingKey` - Ed25519 verifying key type for signature verification
* `VerifyingKey::from_secret_key(&secret_key)` to derive a verifying key from a secret key
* `.verify(&message, &signature)` on `VerifyingKey` to verify a signature
* `ArcisEd25519Signature` - Ed25519 signature type
* `ArcisEd25519Signature::from_bytes(bytes: [u8; 64])` to create a signature from bytes
* `.to_bytes() -> [u8; 64]` on `ArcisEd25519Signature` to serialize a signature

## Hash Functions (SHA3)

* `SHA3_256` - SHA3-256 hasher type (outputs 32 bytes)
* `SHA3_512` - SHA3-512 hasher type (outputs 64 bytes)
* `SHA3_256::new()` / `SHA3_512::new()` to create a hasher instance
* `.digest(&data)` on hasher to compute the hash digest

## Solana Integration

* `SolanaPublicKey` - Solana public key type
* `SerializedSolanaPublicKey` - Serialized Solana public key (stored as `lo: u128, hi: u128`)
* `SolanaPublicKey::from_serialized(data)` to deserialize a Solana public key
* `SolanaPublicKey::from_base58(s)` to create a Solana public key from a base58-encoded byte string

## Machine Learning

* `LogisticRegression` - Logistic regression model type
* `LogisticRegression::new(&coefficients, intercept)` to create a model from coefficients and intercept
* `.predict(&features, threshold)` on `LogisticRegression` to make a binary prediction (returns `bool`)
* `.predict_proba(&features)` on `LogisticRegression` to get the predicted probability (returns `f64`)
* `.predict_log_proba(&features)` on `LogisticRegression` to get the log-odds score (returns `f64`)
* `LinearRegression` - Linear regression model type
* `LinearRegression::new(&coefficients, intercept)` to create a model
* `.predict(&features)` on `LinearRegression` to get the predicted value (returns `f64`)
* `logit(p: f64) -> f64` - Inverse of the standard logistic function
* `expit(x: f64) -> f64` - Standard logistic function (alias for `sigmoid`)

## Math Functions

* `ArcisMath::sigmoid(x: f64) -> f64` to compute the sigmoid function (1 / (1 + e^(-x)))