use proofman_fields::{PrimeField64, CubicExtensionField};
use crate::{HintCol, HintFieldInfoC, HintFieldInfo, HintFieldOutput, HintFieldValue, HintFieldValues, HintFieldValuesVec};
use proofman_starks_lib_c::{
get_hint_field_global_constraints_values_c, get_hint_field_global_constraints_sizes_c,
get_hint_field_global_constraints_c, set_hint_field_global_constraints_c,
};
use std::ffi::c_void;
use std::collections::HashMap;
use proofman_common::{skip_prover_instance, ProofCtx, SetupCtx, ProofmanResult, ProofmanError};
pub fn aggregate_airgroupvals<F: PrimeField64>(
pctx: &ProofCtx<F>,
airgroup_values: &[Vec<F>],
) -> ProofmanResult<Vec<Vec<u64>>> {
const FIELD_EXTENSION: usize = 3;
let mut airgroupvalues = Vec::new();
for agg_types in pctx.global_info.agg_types.iter() {
let mut values = vec![F::ZERO; agg_types.len() * FIELD_EXTENSION];
for (idx, agg_type) in agg_types.iter().enumerate() {
if agg_type.agg_type == 1 {
values[idx * FIELD_EXTENSION] = F::ONE;
}
}
airgroupvalues.push(values);
}
let my_instances = pctx.dctx_get_process_instances();
for (my_instance_idx, instance_id) in my_instances.iter().enumerate() {
let (airgroup_id, _) = pctx.dctx_get_instance_info(*instance_id)?;
for (idx, agg_type) in pctx.global_info.agg_types[airgroup_id].iter().enumerate() {
let mut acc = CubicExtensionField {
value: [
airgroupvalues[airgroup_id][idx * FIELD_EXTENSION],
airgroupvalues[airgroup_id][idx * FIELD_EXTENSION + 1],
airgroupvalues[airgroup_id][idx * FIELD_EXTENSION + 2],
],
};
if !airgroup_values[my_instance_idx].is_empty() {
let instance_airgroup_val = CubicExtensionField {
value: [
airgroup_values[my_instance_idx][idx * FIELD_EXTENSION],
airgroup_values[my_instance_idx][idx * FIELD_EXTENSION + 1],
airgroup_values[my_instance_idx][idx * FIELD_EXTENSION + 2],
],
};
if agg_type.agg_type == 0 {
acc += instance_airgroup_val;
} else {
acc *= instance_airgroup_val;
}
airgroupvalues[airgroup_id][idx * FIELD_EXTENSION] = acc.value[0];
airgroupvalues[airgroup_id][idx * FIELD_EXTENSION + 1] = acc.value[1];
airgroupvalues[airgroup_id][idx * FIELD_EXTENSION + 2] = acc.value[2];
}
}
}
let mut airgroupvalues_u64 = Vec::new();
for (id, agg_types) in pctx.global_info.agg_types.iter().enumerate() {
let mut values = vec![0; agg_types.len() * FIELD_EXTENSION];
for idx in 0..agg_types.len() {
values[idx * FIELD_EXTENSION] =
airgroupvalues[id][idx * FIELD_EXTENSION].to_string().parse::<u64>().unwrap();
values[idx * FIELD_EXTENSION + 1] =
airgroupvalues[id][idx * FIELD_EXTENSION + 1].to_string().parse::<u64>().unwrap();
values[idx * FIELD_EXTENSION + 2] =
airgroupvalues[id][idx * FIELD_EXTENSION + 2].to_string().parse::<u64>().unwrap();
}
airgroupvalues_u64.push(values);
}
Ok(airgroupvalues_u64)
}
fn get_global_hint_f<F: PrimeField64>(
pctx: Option<&ProofCtx<F>>,
sctx: &SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<Vec<HintFieldInfo<F>>> {
let n_hints_values = get_hint_field_global_constraints_values_c(sctx.get_global_bin(), hint_id, hint_field_name);
let mut hint_field_values = vec![HintFieldInfo::default(); n_hints_values as usize];
let mut hint_field_values_c = HintFieldInfoC::from_hint_field_info_vec(&mut hint_field_values);
let mut hint_field_values_c_ptr = hint_field_values_c.as_mut_ptr() as *mut c_void;
get_hint_field_global_constraints_sizes_c(
sctx.get_global_info_file().as_str(),
sctx.get_global_bin(),
hint_field_values_c_ptr,
hint_id,
hint_field_name,
print_expression,
);
HintFieldInfoC::sync_to_hint_field_info(&mut hint_field_values, &hint_field_values_c);
for hint_field_value in hint_field_values.iter_mut() {
hint_field_value.init_buffers();
}
hint_field_values_c = HintFieldInfoC::from_hint_field_info_vec(&mut hint_field_values);
hint_field_values_c_ptr = hint_field_values_c.as_mut_ptr() as *mut c_void;
let publics = if let Some(pctx) = pctx { pctx.get_publics_ptr() } else { std::ptr::null_mut() };
let challenges = if let Some(pctx) = pctx { pctx.get_challenges_ptr() } else { std::ptr::null_mut() };
let proof_values = if let Some(pctx) = pctx { pctx.get_proof_values_ptr() } else { std::ptr::null_mut() };
let airgroup_values = if let Some(pctx) = pctx {
let my_instances = pctx.dctx_get_process_instances();
let mut airgroup_values_air_instances = vec![Vec::new(); my_instances.len()];
for (my_instance_idx, instance_id) in my_instances.iter().enumerate() {
if !skip_prover_instance(pctx, *instance_id)?.0 {
let (airgroup_id, air_id) = pctx.dctx_get_instance_info(*instance_id)?;
let air_instance_id = pctx.dctx_find_air_instance_id(*instance_id)?;
airgroup_values_air_instances[my_instance_idx] =
pctx.get_air_instance_airgroup_values(airgroup_id, air_id, air_instance_id)?;
}
}
let mut airgroupvals = aggregate_airgroupvals(pctx, &airgroup_values_air_instances)?;
let mut airgroup_values_ptrs: Vec<*mut u64> = airgroupvals
.iter_mut() .map(|inner_vec| inner_vec.as_mut_ptr()) .collect();
airgroup_values_ptrs.as_mut_ptr() as *mut *mut u8
} else {
std::ptr::null_mut()
};
get_hint_field_global_constraints_c(
sctx.get_global_info_file().as_str(),
sctx.get_global_bin(),
hint_field_values_c_ptr,
publics,
challenges,
proof_values,
airgroup_values,
hint_id,
hint_field_name,
print_expression,
);
Ok(hint_field_values)
}
pub fn get_hint_field_constant_gc<F: PrimeField64>(
sctx: &SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<HintFieldValue<F>> {
let mut hint_info = get_global_hint_f(None, sctx, hint_id, hint_field_name, print_expression)?;
if hint_info[0].matrix_size != 0 {
return Err(ProofmanError::InvalidHints(format!(
"get_hint_field can only be called with single expressions, but {hint_field_name} is an array"
)));
}
if print_expression {
tracing::info!("HintsInf: {}", std::str::from_utf8(&hint_info[0].expression_line).unwrap());
}
Ok(HintCol::from_hint_field(hint_info.swap_remove(0)))
}
pub fn get_hint_field_gc_constant_a<F: PrimeField64>(
sctx: &SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<HintFieldValuesVec<F>> {
let hint_infos = get_global_hint_f(None, sctx, hint_id, hint_field_name, print_expression)?;
let mut hint_field_values = Vec::new();
for (v, hint_info) in hint_infos.into_iter().enumerate() {
if v == 0 && hint_info.matrix_size != 1 {
return Err(ProofmanError::InvalidHints(
"get_hint_field_m can only be called with an array of expressions!".to_string(),
));
}
if print_expression {
tracing::info!("HintsInf: {}", std::str::from_utf8(&hint_info.expression_line).unwrap());
}
let hint_value = HintCol::from_hint_field(hint_info);
hint_field_values.push(hint_value);
}
Ok(HintFieldValuesVec { values: hint_field_values })
}
pub fn get_hint_field_constant_gc_m<F: PrimeField64>(
sctx: &SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<HintFieldValues<F>> {
let hint_infos = get_global_hint_f(None, sctx, hint_id, hint_field_name, print_expression)?;
let mut hint_field_values = HashMap::with_capacity(hint_infos.len() as usize);
for (v, hint_info) in hint_infos.into_iter().enumerate() {
if v == 0 && hint_info.matrix_size > 2 {
return Err(ProofmanError::InvalidHints(
"get_hint_field_m can only be called with a matrix of expressions!".to_string(),
));
}
let mut pos = Vec::new();
for p in 0..hint_info.matrix_size {
pos.push(hint_info.pos[p as usize]);
}
if print_expression {
tracing::info!("HintsInf: {}", std::str::from_utf8(&hint_info.expression_line).unwrap());
}
hint_field_values.insert(pos, HintCol::from_hint_field(hint_info));
}
Ok(HintFieldValues { values: hint_field_values })
}
pub fn get_hint_field_gc<F: PrimeField64>(
pctx: &ProofCtx<F>,
sctx: &SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<HintFieldValue<F>> {
let mut hint_info = get_global_hint_f(Some(pctx), sctx, hint_id, hint_field_name, print_expression)?;
if hint_info[0].matrix_size != 0 {
return Err(ProofmanError::InvalidHints(format!(
"get_hint_field can only be called with single expressions, but {hint_field_name} is an array"
)));
}
if print_expression {
tracing::info!("HintsInf: {}", std::str::from_utf8(&hint_info[0].expression_line).unwrap());
}
Ok(HintCol::from_hint_field(hint_info.swap_remove(0)))
}
pub fn get_hint_field_gc_a<F: PrimeField64>(
pctx: &ProofCtx<F>,
sctx: &SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<HintFieldValuesVec<F>> {
let hint_infos = get_global_hint_f(Some(pctx), sctx, hint_id, hint_field_name, print_expression)?;
let mut hint_field_values = Vec::new();
for (v, hint_info) in hint_infos.into_iter().enumerate() {
if v == 0 && hint_info.matrix_size != 1 {
return Err(ProofmanError::InvalidHints(
"get_hint_field_m can only be called with an array of expressions!".to_string(),
));
}
if print_expression {
tracing::info!("HintsInf: {}", std::str::from_utf8(&hint_info.expression_line).unwrap());
}
let hint_value = HintCol::from_hint_field(hint_info);
hint_field_values.push(hint_value);
}
Ok(HintFieldValuesVec { values: hint_field_values })
}
pub fn get_hint_field_gc_m<F: PrimeField64>(
pctx: ProofCtx<F>,
sctx: SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
print_expression: bool,
) -> ProofmanResult<HintFieldValues<F>> {
let hint_infos = get_global_hint_f(Some(&pctx), &sctx, hint_id, hint_field_name, print_expression)?;
let mut hint_field_values = HashMap::with_capacity(hint_infos.len() as usize);
for (v, hint_info) in hint_infos.into_iter().enumerate() {
if v == 0 && hint_info.matrix_size > 2 {
return Err(ProofmanError::InvalidHints(
"get_hint_field_m can only be called with a matrix of expressions!".to_string(),
));
}
let mut pos = Vec::new();
for p in 0..hint_info.matrix_size {
pos.push(hint_info.pos[p as usize]);
}
if print_expression {
tracing::info!("HintsInf: {}", std::str::from_utf8(&hint_info.expression_line).unwrap());
}
hint_field_values.insert(pos, HintCol::from_hint_field(hint_info));
}
Ok(HintFieldValues { values: hint_field_values })
}
pub fn set_hint_field_gc<F: PrimeField64>(
pctx: ProofCtx<F>,
sctx: SetupCtx<F>,
hint_id: u64,
hint_field_name: &str,
value: HintFieldOutput<F>,
) {
let mut value_array = Vec::new();
match value {
HintFieldOutput::Field(val) => {
value_array.push(val);
}
HintFieldOutput::FieldExtended(val) => {
value_array.push(val.value[0]);
value_array.push(val.value[1]);
value_array.push(val.value[2]);
}
};
set_hint_field_global_constraints_c(
sctx.get_global_info_file().as_str(),
sctx.get_global_bin(),
pctx.get_proof_values_ptr(),
value_array.as_ptr() as *mut u8,
hint_id,
hint_field_name,
);
}