arcium-anchor 0.4.0

A helper crate for integrating Arcium into Solana programs.
Documentation
enum ComputationMatchingError {
    AccountLenNotMultipleOf32(usize),
    AccountLenTooBig(usize),
    ArgumentMismatch(usize, Parameter),
    NotEnoughParams(usize),
    NotEnoughArguments,
}

impl ComputationMatchingError {
    #[allow(dead_code)]
    fn emit_solana_msg(&self, arguments: &[Argument]) {
        match self {
            ComputationMatchingError::AccountLenNotMultipleOf32(arg_id) => {
                msg!(
                    "Invalid argument : account {:?} len is not a multiple of 32",
                    &arguments[*arg_id],
                );
            }
            ComputationMatchingError::AccountLenTooBig(arg_id) => {
                msg!(
                    "Invalid argument : account {:?} is bigger than the circuit size",
                    &arguments[*arg_id],
                );
            }
            ComputationMatchingError::ArgumentMismatch(arg_id, param) => {
                msg!("Invalid argument {:?} for parameter {:?}", &arguments[*arg_id], param);
            }
            ComputationMatchingError::NotEnoughParams(arg_id) => {
                msg!("Invalid argument : no parameter matching for {:?}", &arguments[*arg_id]);
            }
            ComputationMatchingError::NotEnoughArguments => {
                msg!("Invalid arguments : not enough arguments");
            }
        }
    }
    #[allow(dead_code)]
    const fn const_panic(&self) {
        match self {
            ComputationMatchingError::AccountLenNotMultipleOf32(_) => {
                panic!("Invalid argument : account len is not a multiple of 32");
            }
            ComputationMatchingError::AccountLenTooBig(_) => {
                panic!("Invalid argument : account is bigger than the circuit size");
            }
            ComputationMatchingError::ArgumentMismatch(_, _) => {
                panic!("Invalid argument, mismatch with parameter");
            }
            ComputationMatchingError::NotEnoughParams(_) => {
                panic!("Invalid argument : not enough params");
            }
            ComputationMatchingError::NotEnoughArguments => {
                panic!("Invalid arguments : not enough arguments");
            }
        }
    }
}
const fn arg_match_param(arg: &Argument, param: &Parameter) -> bool {
    match arg {
        Argument::ManticoreAlgo(_) => matches!(param, Parameter::ManticoreAlgo),
        Argument::InputDataset(_) => matches!(param, Parameter::InputDataset),
        Argument::PlaintextBool(_) => matches!(param, Parameter::PlaintextBool),
        Argument::PlaintextU8(_) => matches!(param, Parameter::PlaintextU8),
        Argument::PlaintextU16(_) => matches!(param, Parameter::PlaintextU16),
        Argument::PlaintextU32(_) => matches!(param, Parameter::PlaintextU32),
        Argument::PlaintextU64(_) => matches!(param, Parameter::PlaintextU64),
        Argument::PlaintextU128(_) => matches!(param, Parameter::PlaintextU128),
        Argument::PlaintextFloat(_) => matches!(param, Parameter::PlaintextFloat),
        Argument::EncryptedBool(_) => matches!(param, Parameter::Ciphertext),
        Argument::EncryptedU8(_) => matches!(param, Parameter::Ciphertext),
        Argument::EncryptedU16(_) => matches!(param, Parameter::Ciphertext),
        Argument::EncryptedU32(_) => matches!(param, Parameter::Ciphertext),
        Argument::EncryptedU64(_) => matches!(param, Parameter::Ciphertext),
        Argument::EncryptedU128(_) => matches!(param, Parameter::Ciphertext),
        Argument::EncryptedFloat(_) => matches!(param, Parameter::Ciphertext),
        Argument::ArcisPubkey(_) => matches!(param, Parameter::ArcisPubkey),
        Argument::ArcisSignature(_) => {
            panic!("ArcisSignature are not supposed to reach this function.")
        }
        Argument::Account(_, _, _) => {
            panic!("Accounts are not supposed to reach this function.")
        }
    }
}
const fn args_match_params(arguments: &[Argument], parameters: &[Parameter]) -> core::result::Result<(), ComputationMatchingError> {
    // Validate the arguments match the parameters
    let mut param_idx = 0;
    let mut arg_idx = 0;
    while arg_idx < arguments.len() {
        let arg = &arguments[arg_idx];
        if let Argument::Account(_, _, arg_len) = arg {
            if arg_len.rem_euclid(32) != 0 {
                return Err(ComputationMatchingError::AccountLenNotMultipleOf32(arg_idx));
            }
            param_idx += (*arg_len as usize) / 32;
            // >= is ok, the account finishes right at the end
            if param_idx > parameters.len() {
                return Err(ComputationMatchingError::AccountLenTooBig(arg_idx));
            }
        } else if let Argument::ArcisSignature(..) = arg {
            let mut sig_to_64 = 0u8;
            while sig_to_64 < 64 {
                sig_to_64 += 1;
                if param_idx >= parameters.len() {
                    return Err(ComputationMatchingError::NotEnoughParams(arg_idx));
                }
                let param = &parameters[param_idx];
                if !matches!(param, Parameter::PlaintextU8) {
                    return Err(ComputationMatchingError::ArgumentMismatch(arg_idx, *param));
                }
                param_idx += 1;
            }
        } else {
            if param_idx >= parameters.len() {
                return Err(ComputationMatchingError::NotEnoughParams(arg_idx));
            }
            let param = &parameters[param_idx];
            if !arg_match_param(arg, param) {
                return Err(ComputationMatchingError::ArgumentMismatch(arg_idx, *param));
            }
            param_idx += 1;
        }
        arg_idx += 1;
    }
    if param_idx < parameters.len() {
        return Err(ComputationMatchingError::NotEnoughArguments)
    }

    Ok(())
}