use bc_shamir::MAX_SHARE_COUNT;
use crate::SSKRError;
#[derive(Debug, Clone, PartialEq)]
pub struct Spec {
group_threshold: usize,
groups: Vec<GroupSpec>,
}
impl Spec {
pub fn new(group_threshold: usize, groups: Vec<GroupSpec>) -> Result<Self, SSKRError> {
if group_threshold == 0 {
return Err(SSKRError::GroupThresholdInvalid);
}
if group_threshold > groups.len() {
return Err(SSKRError::GroupThresholdInvalid);
}
if groups.len() > MAX_SHARE_COUNT {
return Err(SSKRError::GroupCountInvalid);
}
Ok(Self {
group_threshold,
groups,
})
}
pub fn group_threshold(&self) -> usize {
self.group_threshold
}
pub fn groups(&self) -> &[GroupSpec] {
&self.groups
}
pub fn group_count(&self) -> usize {
self.groups.len()
}
pub fn share_count(&self) -> usize {
self.groups.iter().map(|g| g.member_count()).sum()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct GroupSpec {
member_threshold: usize,
member_count: usize,
}
impl GroupSpec {
pub fn new(member_threshold: usize, member_count: usize) -> Result<Self, SSKRError> {
if member_count == 0 {
return Err(SSKRError::MemberCountInvalid);
}
if member_count > MAX_SHARE_COUNT {
return Err(SSKRError::MemberCountInvalid);
}
if member_threshold > member_count {
return Err(SSKRError::MemberThresholdInvalid);
}
Ok(Self { member_threshold, member_count })
}
pub fn member_threshold(&self) -> usize {
self.member_threshold
}
pub fn member_count(&self) -> usize {
self.member_count
}
pub fn parse(s: &str) -> Result<Self, SSKRError> {
let parts: Vec<&str> = s.split('-').collect();
if parts.len() != 3 {
return Err(SSKRError::GroupSpecInvalid);
}
let member_threshold = parts[0].parse::<usize>().map_err(|_| SSKRError::GroupSpecInvalid)?;
if parts[1] != "of" {
return Err(SSKRError::GroupSpecInvalid);
}
let member_count = parts[2].parse::<usize>().map_err(|_| SSKRError::GroupSpecInvalid)?;
Self::new(member_threshold, member_count)
}
}
impl Default for GroupSpec {
fn default() -> Self {
Self::new(1, 1).unwrap()
}
}
impl std::fmt::Display for GroupSpec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}-of-{}", self.member_threshold, self.member_count)
}
}