Let's say we have the following confidential instruction that adds 2 encrypted u8s and returns the result as in plaintext:
use arcis_imports::*;
#[encrypted]
mod circuits {
use arcis_imports::*;
pub struct InputValues {
v1: u8,
v2: u8,
}
#[instruction]
pub fn add_together(input_ctxt: Enc<Shared, InputValues>) -> u16 {
let input = input_ctxt.to_arcis();
let sum = input.v1 as u16 + input.v2 as u16;
sum.reveal()
}
}
We want to input the values x = 42 and y = 101 into this instruction. To do this, we first have to build the parameters for the confidential instruction correctly:
import { RescueCipher, getArciumEnv, x25519 } from "@arcium-hq/arcium-sdk";
import { randomBytes } from "crypto";
// Our confidential instruction takes two encrypted `u8` values as input, so we need to provide two ciphertext values which are represented as `[u8; 32]` in our Solana program.
const val1 = BigInt(1);
const val2 = BigInt(2);
const plaintext = [val1, val2];
Now that we have the inputs, we need to encrypt them. This is done using the RescueCipher class with some info about the MPC cluster we want to use:
// Generate a random private key for x25519 elliptic curve Diffie-Hellman key exchange.
const privateKey = x25519.utils.randomPrivateKey();
// Derive the public key from the private key.
const publicKey = x25519.getPublicKey(privateKey);
// Generate a random nonce for the encryption.
const nonce = randomBytes(16);
// Get the shared secret with the cluster.
const sharedSecret = x25519.getSharedSecret(privateKey, mxePublicKey);
// Initialize the cipher with the shared secret.
const cipher = new RescueCipher(sharedSecret);
// Encrypt the plaintext, and serialize it to a `[u8; 32]` array.
const ciphertext = cipher.encrypt(plaintext, nonce);
To decrypt the data, again it follows a similar pattern:
// Initialize the cipher with the shared secret.
const cipher = new RescueCipher(sharedSecret);
const plaintext = cipher.decrypt(ciphertext, nonce);