use crate::error::{Error, Result};
use crate::trust::bls::BlsKeypair;
use core::ptr;
use nwep_sys as sys;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CheckpointStatus {
Fresh,
Warning,
Stale,
}
impl CheckpointStatus {
pub(crate) fn from_code(code: core::ffi::c_int) -> CheckpointStatus {
match code {
sys::NWEP_CHECKPOINT_FRESH => CheckpointStatus::Fresh,
sys::NWEP_CHECKPOINT_WARNING => CheckpointStatus::Warning,
_ => CheckpointStatus::Stale,
}
}
}
pub struct Checkpoint {
raw: *mut sys::nwep_checkpoint,
}
impl Checkpoint {
pub fn decode(bytes: &[u8]) -> Result<Checkpoint> {
let mut raw: *mut sys::nwep_checkpoint = ptr::null_mut();
Error::check(unsafe {
sys::nwep_checkpoint_decode(bytes.as_ptr(), bytes.len(), &mut raw)
})?;
Ok(Checkpoint { raw })
}
pub fn staleness(&self, now_secs: i64) -> Result<CheckpointStatus> {
let rc = unsafe { sys::nwep_checkpoint_staleness(self.raw, now_secs) };
if rc < 0 {
return Err(Error::from_code(rc));
}
Ok(CheckpointStatus::from_code(rc))
}
pub fn as_ptr(&self) -> *mut sys::nwep_checkpoint {
self.raw
}
}
impl Drop for Checkpoint {
fn drop(&mut self) {
unsafe { sys::nwep_checkpoint_free(self.raw) };
}
}
pub fn genesis_checkpoint(founders: &[(&BlsKeypair, u8)], threshold: usize) -> Result<Vec<u8>> {
if founders.is_empty() || threshold == 0 || threshold > founders.len() {
return Err(Error::ConfigInvalid);
}
let n = founders.len();
let mut secrets = vec![0u8; n * sys::NWEP_BLS_SECKEY_SIZE];
let mut pubkeys = vec![0u8; n * sys::NWEP_BLS_PUBKEY_SIZE];
let mut indices = vec![0u8; n];
for (i, (kp, index)) in founders.iter().enumerate() {
let sk = i * sys::NWEP_BLS_SECKEY_SIZE;
let pk = i * sys::NWEP_BLS_PUBKEY_SIZE;
secrets[sk..sk + sys::NWEP_BLS_SECKEY_SIZE].copy_from_slice(kp.secret());
pubkeys[pk..pk + sys::NWEP_BLS_PUBKEY_SIZE].copy_from_slice(kp.public_key());
indices[i] = *index;
}
let mut len = 0usize;
let size_rc = unsafe {
sys::nwep_genesis_checkpoint_create(
secrets.as_ptr(),
pubkeys.as_ptr(),
indices.as_ptr(),
n,
threshold,
ptr::null_mut(),
&mut len,
)
};
if let Err(e) = Error::check(size_rc) {
unsafe { sys::nwep_zeroize(secrets.as_mut_ptr().cast(), secrets.len()) };
return Err(e);
}
let mut out = vec![0u8; len];
let rc = unsafe {
sys::nwep_genesis_checkpoint_create(
secrets.as_ptr(),
pubkeys.as_ptr(),
indices.as_ptr(),
n,
threshold,
out.as_mut_ptr(),
&mut len,
)
};
unsafe { sys::nwep_zeroize(secrets.as_mut_ptr().cast(), secrets.len()) };
Error::check(rc)?;
out.truncate(len);
Ok(out)
}