use crate::{
constants::COEFFICIENTS_IN_RING_ELEMENT, encoding, polynomial::PolynomialRingElement,
simd::traits::Operations, VerificationError,
};
#[inline(always)]
pub(crate) fn serialize<SIMDUnit: Operations>(
commitment_hash: &[u8],
signer_response: &[PolynomialRingElement<SIMDUnit>],
hint: &[[i32; COEFFICIENTS_IN_RING_ELEMENT]],
commitment_hash_size: usize,
columns_in_a: usize,
rows_in_a: usize,
gamma1_exponent: usize,
gamma1_ring_element_size: usize,
max_ones_in_hint: usize,
signature: &mut [u8],
) {
let mut offset = 0;
signature[offset..offset + commitment_hash_size].copy_from_slice(commitment_hash);
offset += commitment_hash_size;
for i in 0..columns_in_a {
encoding::gamma1::serialize::<SIMDUnit>(
&signer_response[i],
&mut signature[offset..offset + gamma1_ring_element_size],
gamma1_exponent,
);
offset += gamma1_ring_element_size;
}
let mut true_hints_seen = 0;
for i in 0..rows_in_a {
for j in 0..hint[i].len() {
if hint[i][j] == 1 {
signature[offset + true_hints_seen] = j as u8;
true_hints_seen += 1;
}
}
signature[offset + max_ones_in_hint + i] = true_hints_seen as u8;
}
}
#[inline(always)]
pub(crate) fn deserialize<SIMDUnit: Operations>(
columns_in_a: usize,
rows_in_a: usize,
commitment_hash_size: usize,
gamma1_exponent: usize,
gamma1_ring_element_size: usize,
max_ones_in_hint: usize,
signature_size: usize,
serialized: &[u8],
out_commitment_hash: &mut [u8],
out_signer_response: &mut [PolynomialRingElement<SIMDUnit>],
out_hint: &mut [[i32; COEFFICIENTS_IN_RING_ELEMENT]],
) -> Result<(), VerificationError> {
debug_assert!(serialized.len() == signature_size);
let (commitment_hash, rest_of_serialized) = serialized.split_at(commitment_hash_size);
out_commitment_hash[0..commitment_hash_size].copy_from_slice(commitment_hash);
let (signer_response_serialized, hint_serialized) =
rest_of_serialized.split_at(gamma1_ring_element_size * columns_in_a);
for i in 0..columns_in_a {
encoding::gamma1::deserialize::<SIMDUnit>(
gamma1_exponent,
&signer_response_serialized
[i * gamma1_ring_element_size..(i + 1) * gamma1_ring_element_size],
&mut out_signer_response[i],
);
}
let mut previous_true_hints_seen = 0usize;
for i in 0..rows_in_a {
let current_true_hints_seen = hint_serialized[max_ones_in_hint + i] as usize;
if (current_true_hints_seen < previous_true_hints_seen)
|| (previous_true_hints_seen > max_ones_in_hint)
{
return Err(VerificationError::MalformedHintError);
}
for j in previous_true_hints_seen..current_true_hints_seen {
if j > previous_true_hints_seen && hint_serialized[j] <= hint_serialized[j - 1] {
return Err(VerificationError::MalformedHintError);
}
set_hint(out_hint, i, hint_serialized[j] as usize);
}
previous_true_hints_seen = current_true_hints_seen;
}
for j in previous_true_hints_seen..max_ones_in_hint {
if hint_serialized[j] != 0 {
return Err(VerificationError::MalformedHintError);
}
}
Ok(())
}
#[inline(always)]
fn set_hint(out_hint: &mut [[i32; 256]], i: usize, j: usize) {
out_hint[i][j] = 1
}