use log::error;
use serde::{Deserialize, Serialize};
pub const DEFAULT_MAX_LIABILITY: u64 = 2u64.pow(DEFAULT_RANGE_PROOF_UPPER_BOUND_BIT_LENGTH as u32);
pub const DEFAULT_RANGE_PROOF_UPPER_BOUND_BIT_LENGTH: u8 = 32u8;
pub const ALLOWED_RANGE_PROOF_UPPER_BIT_SIZES: [u8; 4] = [8, 16, 32, 64];
#[doc = include_str!("./shared_docs/max_liability.md")]
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
pub struct MaxLiability(u64);
impl MaxLiability {
pub fn as_u64(&self) -> u64 {
self.0
}
pub fn as_range_proof_upper_bound_bit_length(&self) -> u8 {
let pow_2 = (self.0 as f64).log2() as u8;
*ALLOWED_RANGE_PROOF_UPPER_BIT_SIZES
.iter()
.find(|i| **i > pow_2)
.unwrap_or_else(|| {
panic!(
"[BUG] It should not be possible for the base 2 logarithm of {} to be above 64",
self.0
)
})
}
}
impl From<u64> for MaxLiability {
fn from(max_liability: u64) -> Self {
Self(max_liability)
}
}
impl Default for MaxLiability {
fn default() -> Self {
Self(DEFAULT_MAX_LIABILITY)
}
}
use std::str::FromStr;
impl FromStr for MaxLiability {
type Err = MaxLiabilityError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(MaxLiability(u64::from_str(s)?))
}
}
use clap::builder::{OsStr, Str};
impl From<MaxLiability> for OsStr {
fn from(max_liability: MaxLiability) -> OsStr {
OsStr::from(Str::from(max_liability.as_u64().to_string()))
}
}
#[derive(thiserror::Error, Debug)]
pub enum MaxLiabilityError {
#[error("Malformed string input for u64 type")]
MalformedString(#[from] std::num::ParseIntError),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_max_liability_is_in_allowed_list() {
let pow_2 = (DEFAULT_MAX_LIABILITY as f64).log2() as u8;
assert!(ALLOWED_RANGE_PROOF_UPPER_BIT_SIZES
.iter()
.find(|i| **i == pow_2)
.is_some());
}
#[test]
fn upper_bound_bit_length_works_for_100() {
let input_max_liability = 100u64;
let max_liability = MaxLiability(input_max_liability);
let logarithm_of_input_truncated = (input_max_liability as f64).log2() as u8;
assert_eq!(logarithm_of_input_truncated, 6u8);
let nearest_pow_2_greater_than = 8u8;
assert_eq!(
max_liability.as_range_proof_upper_bound_bit_length(),
nearest_pow_2_greater_than
);
}
}