use alloc::vec::Vec;
use core::cmp::Ordering;
use serde::Serialize;
use crate::error::ErrorBits;
pub const ALI_LABEL: &str = "air-composition";
pub const DEEP_LABEL: &str = "deep-ali";
pub const LDT_LABEL: &str = "low-degree-test";
pub const LDT_QUERY_LABEL: &str = "ldt-query-phase";
pub const LDT_COMMIT_LABEL: &str = "ldt-commit-phase";
pub const BATCH_LABEL: &str = "batch-combination";
pub const COLLISION_LABEL: &str = "commitment-collision";
#[derive(Copy, Clone, Debug, PartialEq, Serialize)]
pub struct SecurityTerm {
pub label: &'static str,
pub bits: ErrorBits,
}
impl SecurityTerm {
pub const fn new(label: &'static str, bits: ErrorBits) -> Self {
Self { label, bits }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize)]
#[non_exhaustive]
pub enum Regime {
UniqueDecoding,
ListDecoding { m: usize },
Conjectured,
}
#[derive(Clone, Debug, Serialize)]
pub struct RegimeReport {
pub regime: Regime,
terms: Vec<SecurityTerm>,
}
impl RegimeReport {
pub(crate) fn new(regime: Regime, terms: Vec<SecurityTerm>) -> Self {
debug_assert!(
!terms.is_empty(),
"a regime report must carry at least one term"
);
Self { regime, terms }
}
pub fn terms(&self) -> &[SecurityTerm] {
&self.terms
}
pub fn binding(&self) -> SecurityTerm {
self.terms
.iter()
.copied()
.min_by(|a, b| {
a.bits
.bits()
.partial_cmp(&b.bits.bits())
.unwrap_or(Ordering::Equal)
})
.expect("a regime report always carries the ALI/DEEP/LDT/collision terms")
}
pub fn security_bits(&self) -> f64 {
self.binding().bits.bits()
}
}
#[derive(Clone, Debug, Serialize)]
pub struct SecurityReport {
pub udr: RegimeReport,
pub ldr: Option<RegimeReport>,
}
impl SecurityReport {
pub fn security_bits(&self) -> f64 {
let ldr = self.ldr.as_ref().map_or(0.0, RegimeReport::security_bits);
self.udr.security_bits().max(ldr)
}
pub fn binding(&self) -> (Regime, SecurityTerm) {
match &self.ldr {
Some(ldr) if ldr.security_bits() > self.udr.security_bits() => {
(ldr.regime, ldr.binding())
}
_ => (self.udr.regime, self.udr.binding()),
}
}
}