Arcium Docs
arcium.com@ArciumHQ
  • Documentation
  • Developers
  • Intro to Arcium
  • Installation
    • Arcup Version Manager
  • Hello World with Arcium
  • Arcium Computation Lifecycle
  • Encryption
    • Sealing aka re-encryption
  • Arcis
    • Operations
    • Types
    • Input/Output
    • Best practices
  • Invoking a Computation from your Solana program
    • Computation Definition Accounts
    • Callback Accounts
  • JavaScript Client
    • Encrypting inputs
    • Tracking callbacks
  • Callback Server
  • Current Limitations
Powered by GitBook
On this page
  1. Arcis

Input/Output

PreviousTypesNextBest practices

Last updated 22 days ago

Inputs and outputs in confidential instructions are handled in the same way. Arcium network does not mutate any state itself. Both inputs and outputs can be encrypted or plaintext data, either being passed by value or by reference. Passing by reference is only possible for account data, where the Arcium nodes will be able fetching data from account. This is beneficial for accounts where data is larger than what can fit in a single Solana transaction, or if you want to avoid storage costs for the data while the computation is in progress (as each input has to be written to a computation object for the duration of the computation).

Encrypted data is passed as an Enc<Owner, T> generic type, where Owner specifies who can decrypt the data (either Shared or Mxe), and T is the underlying data type being encrypted. Learn more about .

struct Order {
    size: u64,
    bid: bool,
    owner: u128,
}

#[instruction]
pub fn add_order(
    order_ctxt: Enc<Shared, Order>,
    ob_ctxt: Enc<Mxe, &OrderBook>,
) -> Enc<Mxe, OrderBook> {
    let order = order_ctxt.to_arcis();
    let mut ob = *(ob_ctxt.to_arcis());
    let mut found = false;
    for i in 0..ORDER_BOOK_SIZE {
        let overwrite = ob.orders[i].size == 0 && !found;
        if overwrite {
            ob.orders[i] = order;
        }
        found = overwrite || found;
    }
    ob_ctxt.owner.from_arcis(ob)
}

Let's use this example to understand how to pass inputs into confidential instructions, compute on them and return outputs. Here, we are trying to add an order to an existing order book.

In this example, order_ctxt: Enc<Shared, Order> is passed by value, meaning the entire encrypted order data is submitted onchain. In contrast, ob_ctxt: Enc<Mxe, &OrderBook> is passed by reference - only the account's public key is submitted onchain, and the MPC nodes will fetch the actual data from that account during computation. This is particularly useful for large data structures like order books that might not fit in a single transaction.

In order to use the parameters order_ctxt and ob_ctxt for computation, we need to convert them to corresponding secret shares for the nodes to compute in MPC. This can be done by calling to_arcis function on any Enc generic parameter. This does not reveal the plaintext data underneath to the nodes during the process.

Here, the order parameter disappears after the confidential instruction has been processed (just as you'd expect in regular rust too). To output the new order book, we convert it back using from_arcis on ob_ctxt.owner field which defines the owner, aka the party which encrypted the data, to get the new Enc<Origin, T> type, and return it.

Currently, as many outputs as can fit in a single transaction are sent in the callback transaction, whereas the rest are all sent to the for state updates. This means that you might need to make state changes through the callback server, and are responsible for updating the on-chain accounts, if needed.

encryption in Arcium Network
callback server