Hello World
The Arcium tooling suite for writing MXEs (MPC eXecution Environments) is built on top of Anchor, so if you’re familiar with Anchor, you should find Arcium to be a familiar experience, except that you’re using thearcium CLI instead of anchor.
To initialize a new MXE project, you can therefore simply run:
- The
Arcium.tomlfile, which contains the configuration for the Arcium tooling suite. - The
encrypted-ixsdirectory. This is where we write all our code that is meant to operate on encrypted data and therefore runs in MPC. This code is written using our own Rust framework called Arcis. This will already be populated with a simple example calledadd_together.rs. Let’s take a closer look at it.
Our first encrypted instruction
use arcis::*; imports all the necessary types and functions for writing encrypted instructions with Arcis. The #[encrypted] attribute marks a module that contains encrypted instructions. Inside this module, we define a struct InputValues that contains the two values we want to encrypt and pass to the encrypted instruction.
The #[instruction] macro marks the function as an entry point for MPC execution. While you can write helper functions without this attribute, only functions marked with #[instruction] will be compiled into individual circuits that can be called onchain.
The function add_together takes an encrypted input parameter of type Enc<Shared, InputValues>. Let’s break this down:
Enc<Owner, Data>is Arcium’s encrypted data typeSharedmeans the data is encrypted with a shared secret between the client and MXE (both can decrypt it)InputValuesis the actual data structure being encrypted (our struct with v1 and v2)- The alternative to
SharedisMxe, where only the MXE can decrypt the data
input_ctxt.to_arcis()converts the input into a form we can operate on within the MPC environment.- We perform the addition operation, casting the u8 values to u16 to prevent overflow.
input_ctxt.owner.from_arcis(sum)converts the encrypted sum into an encrypted format that can be stored onchain, while maintaining encryption with the shared secret between the client and the MXE.
Calling it from Solana
Now that we’ve written our first confidential instruction, let’s see how we can use it from within a Solana program. Our default project already contains a Solana program in theprograms/ directory. Let’s take a closer look at it too:
InitAddTogetherCompDef, AddTogether, and AddTogetherCallback account structs are not included here, but they are automatically generated when you run arcium init. Here’s a simplified version of what AddTogether looks like:
#[arcium_program] macro (which replaces Anchor’s #[program] macro) and that for every confidential instruction, we generally have three instructions in the Solana program:
init_add_together_comp_def: This is the instruction that initializes the confidential instruction definition. It is used to set up the computation definition and is therefore only called once prior to the first invocation of the confidential instruction. More info on this can be found here.add_together: This is the instruction that invokes the confidential instruction. It takes in the arguments for the confidential instruction and queues it for execution using the Arcium program. More info on this can be found here.add_together_callback: This is the instruction that is called by the MPC cluster when the confidential instruction has finished executing which returns our result. More info on this can be found here.
Building and testing
Similar to Anchor, the confidential instructions and Solana programs can be built usingarcium build. Testing is done using the @arcium-hq/client TypeScript library (more information can be found here) by default and can be run using arcium test (make sure you have installed the npm dependencies prior by running yarn or npm install in your project directory). By default, this runs against a local cluster. To test against devnet or mainnet, use arcium test --cluster devnet (requires cluster configuration in Arcium.toml - see the migration guide).
Let’s take a quick look at the default test file. Note that some helper functions and imports are excluded for brevity, but you can find the complete examples in your generated project:
initAddTogetherCompDef: Call theinit_add_together_comp_definstruction to initialize the confidential instruction definition. (only need to be called once after the program is deployed)getMXEPublicKeyWithRetry: Fetch the MXE’s x25519 public key.x25519.utils.randomSecretKey: Generate a random private key for the x25519 key exchange.x25519.getPublicKey: Generate the public key corresponding to the private key we generated above.x25519.getSharedSecret: Generate the shared secret with the MXE cluster using a x25519 key exchange.cipher = new RescueCipher(sharedSecret): Initialize the Rescue cipher (the constructor internally performs a key derivation based on the Rescue-Prime hash function, you can learn more here)cipher.encrypt: Encrypt the inputs for the confidential instruction.awaitEvent: Wait for thesumEventevent to be emitted by the program on finalization of the computation (in the callback instruction).addTogether: Call theadd_togetherinstruction to invoke the confidential instruction.awaitComputationFinalization: Since waiting for an Arcium computation is not the same as waiting for one Solana transaction (because the MPC cluster must finish the computation and invoke the callback), this function is used, which is provided by the Arcium TypeScript library.
Ready to Deploy?
Now that you have built and tested your MXE locally, you are probably eager to see it running on devnet! Head over to our deployment guide where we’ll walk you through getting your MXE live on Solana devnet. We’ll cover everything from choosing the right RPC endpoint to initializing your computation definitions.What’s Next?
Now that you have built your first MXE, you are ready to deploy it to testnet. Follow the deployment guide to get your MXE running on Solana devnet and test with real encrypted computations.Learn Arcis
To build more complex circuits, learn the Arcis framework:- Thinking in MPC — Understand why Arcis has constraints like fixed loops and both-branches-execute
- Quick Reference — Syntax cheatsheet for when you’re coding