Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.arcium.com/llms.txt

Use this file to discover all available pages before exploring further.

Why computation definitions exist

When you write a confidential instruction using Arcis, it gets compiled into an MPC circuit - essentially a program that the MPC nodes can execute securely on confidential data. But here’s the challenge: how do the MPC nodes know what circuit to run when your Solana program calls for a computation? That’s where Computation Definition Accounts come in. They serve as the bridge between your Solana program and the MPC network, storing both the circuit itself and metadata about how to execute it. Think of it as uploading your confidential instruction to the blockchain so the MPC nodes can access it when needed.

Computation definition accounts

When we define a confidential instruction using Arcis, we need the MPC cluster that will execute this confidential instruction to have access to the confidential instruction itself, its interface, and some more metadata. This is done by defining a ComputationDefinitionAccount struct, which consists of two parts:
  1. The confidential instruction metadata and interface.
  2. The raw MPC bytecode.
The interface stores expected inputs, outputs, required accounts, and execution metadata. This data lives in an account with the seeds b"ComputationDefinitionAccount", mxe_program_id, comp_def_offset. The first seed is exported by the Arcium Anchor SDK, the second is your MXE program ID, and the third is a confidential-instruction-specific offset. comp_def_offset is sha256(<confidential_instruction_name>).slice(0,4) interpreted as a little-endian u32. The derive_comp_def_pda! macro computes the ComputationDefinitionAccount address for you. The MPC bytecode is stored inside account(s) with the seeds b"ComputationDefinitionRaw", comp_def_acc, i. Like above, the first is exported as a constant by the Arcium Anchor SDK, the second is the computation definition account we defined above, and the third is an index starting from 0 up to however many accounts we need to store the full MPC bytecode.

Usage

When working locally, you theoretically don’t need to care about the MPC bytecode accounts, as the Arcium CLI will handle the creation and management of these accounts for you. You do however need to create the interface ComputationDefinitionAccount, which can easily be done with the Arcium Anchor tooling. Let’s say we want to deploy a confidential instruction called add_together:
pub fn init_add_together_comp_def(ctx: Context<InitAddTogetherCompDef>) -> Result<()> {
    init_computation_def(ctx.accounts, None)?;
    Ok(())
}

#[init_computation_definition_accounts("add_together", payer)]
#[derive(Accounts)]
pub struct InitAddTogetherCompDef<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
    #[account(
        mut,
        address = derive_mxe_pda!()
    )]
    pub mxe_account: Box<Account<'info, MXEAccount>>,
    #[account(mut)]
    /// CHECK: comp_def_account, checked by arcium program.
    pub comp_def_account: UncheckedAccount<'info>,
    #[account(mut, address = derive_mxe_lut_pda!(mxe_account.lut_offset_slot))]
    /// CHECK: address_lookup_table, checked by arcium program.
    pub address_lookup_table: UncheckedAccount<'info>,
    #[account(address = LUT_PROGRAM_ID)]
    /// CHECK: lut_program is the Address Lookup Table program.
    pub lut_program: UncheckedAccount<'info>,
    pub arcium_program: Program<'info, Arcium>,
    pub system_program: Program<'info, System>,
}
Call this instruction once before using the confidential instruction. When you no longer need the computation definition, follow the account lifecycle to deactivate and close it.

Off-chain circuit sources

For larger circuits, you can store the compiled circuit off-chain and pass an OffChainCircuitSource as the second argument to init_computation_def:
use arcium_client::idl::arcium::types::{CircuitSource, OffChainCircuitSource};
use arcium_macros::circuit_hash;

pub fn init_add_together_comp_def(ctx: Context<InitAddTogetherCompDef>) -> Result<()> {
    init_computation_def(
        ctx.accounts,
        Some(CircuitSource::OffChain(OffChainCircuitSource {
            source: "https://your-storage.com/path/to/add_together.arcis".to_string(),
            hash: circuit_hash!("add_together"),
        })),
    )?;
    Ok(())
}
The circuit_hash! macro embeds the SHA-256 hash from build/{circuit_name}.hash at compile time; Arx nodes verify it when fetching the circuit. For the full off-chain workflow, see Deployment.