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> {
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;
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 = ¶meters[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 = ¶meters[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(())
}