use crate::error::Error;
use crate::index::error::IndexError;
use crate::index::PadStatus;
use log::{debug, info};
use mutant_protocol::StorageMode;
use std::ops::Range;
use super::{IndexEntry, MasterIndex};
impl MasterIndex {
pub fn create_key(
&mut self,
key_name: &str,
data_bytes: &[u8],
mode: StorageMode,
public: bool,
) -> Result<(Vec<super::PadInfo>, Vec<Range<usize>>), Error> {
if self.index.contains_key(key_name) {
return Err(IndexError::KeyAlreadyExists(key_name.to_string()).into());
}
let chunk_ranges = self.chunk_data(data_bytes, mode);
let pads = self.acquire_pads(data_bytes, &chunk_ranges)?;
if public {
let mut index_pad_info = self._acquire_pads_internal(1)?[0].clone();
index_pad_info.chunk_index = 0;
self.index.insert(
key_name.to_string(),
IndexEntry::PublicUpload(index_pad_info, pads.clone()),
);
} else {
self.index
.insert(key_name.to_string(), IndexEntry::PrivateKey(pads.clone()));
}
self.save(self.network_choice)?;
Ok((pads, chunk_ranges))
}
pub fn remove_key(&mut self, key_name: &str) -> Result<(), Error> {
let mut pads_to_free = Vec::new();
let mut pads_to_verify = Vec::new();
if let Some(entry) = self.index.get_mut(key_name) {
if let IndexEntry::PrivateKey(pads) = entry {
pads.iter_mut().for_each(|p| {
if p.status != PadStatus::Generated {
p.status = PadStatus::Free;
pads_to_free.push(p.clone());
} else {
pads_to_verify.push(p.clone());
}
p.checksum = 0;
p.size = 0;
});
} else if let IndexEntry::PublicUpload(index, pads) = entry {
if index.status != PadStatus::Generated {
index.status = PadStatus::Free;
pads_to_free.push(index.clone());
} else {
pads_to_verify.push(index.clone());
}
pads.iter_mut().for_each(|p| {
if p.status != PadStatus::Generated {
p.status = PadStatus::Free;
pads_to_free.push(p.clone());
} else {
pads_to_verify.push(p.clone());
}
p.checksum = 0;
p.size = 0;
});
}
}
debug!(
"Removing key {} with {} pads to free and {} pads to verify",
key_name,
pads_to_free.len(),
pads_to_verify.len()
);
self.free_pads.extend(pads_to_free);
self.pending_verification_pads.extend(pads_to_verify);
self.index.remove(key_name);
self.save(self.network_choice)?;
info!("Removed key {}", key_name);
Ok(())
}
pub fn contains_key(&self, key_name: &str) -> bool {
self.index.contains_key(key_name)
}
pub fn get_pads(&self, key_name: &str) -> Vec<super::PadInfo> {
if let Some(entry) = self.index.get(key_name) {
match entry {
IndexEntry::PrivateKey(pads) => pads.clone(),
IndexEntry::PublicUpload(_index, pads) => pads.clone(),
}
} else {
Vec::new()
}
}
pub fn get_entry(&self, key_name: &str) -> Option<&IndexEntry> {
self.index.get(key_name)
}
pub fn add_entry(&mut self, key_name: &str, entry: IndexEntry) -> Result<(), Error> {
self.index.insert(key_name.to_string(), entry);
self.save(self.network_choice)?;
Ok(())
}
pub fn update_entry(&mut self, key_name: &str, entry: IndexEntry) -> Result<bool, Error> {
if let Some(existing_entry) = self.index.get_mut(key_name) {
match existing_entry {
IndexEntry::PrivateKey(existing_pads) => match &entry {
IndexEntry::PrivateKey(pads) => {
if pads[0].last_known_counter > existing_pads[0].last_known_counter {
*existing_entry = entry;
self.save(self.network_choice)?;
Ok(true)
} else {
Ok(false)
}
}
_ => panic!("Cannot update public key with private key"),
},
IndexEntry::PublicUpload(existing_index, _existing_pads) => match &entry {
IndexEntry::PublicUpload(index, _pads) => {
if index.last_known_counter > existing_index.last_known_counter {
*existing_entry = entry;
self.save(self.network_choice)?;
Ok(true)
} else {
Ok(false)
}
}
_ => panic!("Cannot update private key with public key"),
},
}
} else {
Err(IndexError::KeyNotFound(key_name.to_string()).into())
}
}
pub fn is_public(&self, key_name: &str) -> bool {
self.index.get(key_name).map_or(false, |entry| match entry {
IndexEntry::PublicUpload(_, _) => true,
IndexEntry::PrivateKey(_) => false,
})
}
pub fn list(&self) -> std::collections::BTreeMap<String, IndexEntry> {
let mut keys = self.index.clone();
keys.iter_mut().for_each(|(_, entry)| {
if let IndexEntry::PrivateKey(pads) = entry {
pads.iter_mut().for_each(|p| p.sk_bytes = vec![0; 32]);
} else if let IndexEntry::PublicUpload(index, pads) = entry {
pads.iter_mut().for_each(|p| p.sk_bytes = vec![0; 32]);
index.sk_bytes = vec![0; 32];
}
});
keys
}
}