Skip to content

Commit

Permalink
Merge pull request #56 from HerodotusDev/feat/better-in-store-table-e…
Browse files Browse the repository at this point in the history
…rror-not-found

Feat/better in store table error not found
  • Loading branch information
beeinger authored Aug 16, 2024
2 parents 7c54643 + b0f7064 commit c2e1beb
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 13 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "accumulators"
version = "0.4.2"
version = "0.4.3"
edition = "2021"
license-file = "LICENSE"
description = "Complete package of multiple Accumulators with Stores and hashing functions (Hashers)"
Expand Down Expand Up @@ -33,7 +33,6 @@ indexmap = "2.1.0"
strum = "0.25" # better enums
strum_macros = "0.25" # better enums


[dev-dependencies]
criterion = { version = "0.4", features = [
"html_reports",
Expand Down
59 changes: 48 additions & 11 deletions src/store/table.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{Store, StoreError};
use std::collections::HashMap;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::hash::Hash;
use std::sync::Arc;
use thiserror::Error;
Expand Down Expand Up @@ -48,11 +49,36 @@ pub struct SubMMR {
pub store: Arc<dyn Store>,
}

#[derive(Error, Debug)]
pub struct MissingValues {
pub stores_with_missing_keys: HashMap<String, Vec<String>>,
}

impl Display for MissingValues {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let mut formatted_output = String::new();

//? Iterate over the HashMap to build the string in the required format
for (store, keys) in &self.stores_with_missing_keys {
let keys_str = keys.join(", ");
formatted_output.push_str(&format!("{}: {}", store, keys_str));
formatted_output.push_str("; ");
}

//? Remove the trailing "; " for better formatting
if !formatted_output.is_empty() {
formatted_output.truncate(formatted_output.len() - 2);
}

write!(f, "{{{}}}", formatted_output)
}
}

/// An error that can occur when using an InStoreTable
#[derive(Error, Debug)]
pub enum InStoreTableError {
#[error("Some keys were not found")]
NotFound,
#[error("Some keys were not found for stores: {0}")]
NotFound(#[from] MissingValues),
#[error("Store error: {0}")]
Store(#[from] StoreError),
#[error("Could not decode store key")]
Expand Down Expand Up @@ -137,29 +163,40 @@ impl InStoreTable {
&self,
sub_keys: Vec<SubKey>,
) -> Result<HashMap<String, String>, InStoreTableError> {
let requested_len = sub_keys.len();
let stores_and_keys = (self.get_stores_and_full_keys)(self, sub_keys);
let stores_and_keys = (self.get_stores_and_full_keys)(self, sub_keys.clone())?;

let mut keyless = HashMap::new();
for store_and_keys in stores_and_keys? {
let (store, keys) = store_and_keys;
let mut stores_with_missing_keys = HashMap::new();
let mut retrieved_sub_keys_as_string = HashMap::new();
for (store, keys) in stores_and_keys {
let keys_ref: Vec<&str> = keys.iter().map(AsRef::as_ref).collect();
let fetched = store.get_many(keys_ref).await?;

//? Checking for missing keys
let missing_keys = keys
.into_iter()
.filter(|key| !fetched.contains_key(&key.to_string()))
.collect::<Vec<_>>();
if !missing_keys.is_empty() {
stores_with_missing_keys.insert(store.id(), missing_keys);
}

//? Strapping full key to sub_key format and saving in the final hash map
for (key, value) in fetched.iter() {
let new_key: String = if key.contains(':') {
key.split(':').skip(2).collect::<Vec<&str>>().join(":")
} else {
key.clone()
};
keyless.insert(new_key, value.clone());
retrieved_sub_keys_as_string.insert(new_key, value.clone());
}
}

if keyless.len() != requested_len {
Err(InStoreTableError::NotFound)
if !stores_with_missing_keys.is_empty() {
Err(InStoreTableError::NotFound(MissingValues {
stores_with_missing_keys,
}))
} else {
Ok(keyless)
Ok(retrieved_sub_keys_as_string)
}
}

Expand Down
22 changes: 22 additions & 0 deletions tests/mmr/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,3 +789,25 @@ async fn should_get_a_stable_root_hash_for_given_args_poseidon_hasher() {

assert_eq!(stable_root_hash, root_hash);
}

#[tokio::test]
async fn timestamp_remappers_test() {
let store = InMemoryStore::default();
let hasher = Arc::new(StarkPoseidonHasher::new(Some(false)));
let store = Arc::new(store);

let mut mmr = MMR::new(store, hasher.clone(), None);

mmr.append("1715180160".to_string()).await.unwrap();
mmr.append("1715180172".to_string()).await.unwrap();

let element_count = mmr.elements_count.get().await.unwrap();
println!("element_count: {}", element_count);
let bag = mmr.bag_the_peaks(Some(element_count)).await.unwrap();
println!("bag: {}", bag);
let root_hash = mmr.calculate_root_hash(&bag, element_count).unwrap();
println!("root_hash: {}", root_hash);

let correct_root_hash = "0x32f5a2949cac3d06e854701c5a2a00ed51c0475a31c1bc17cc6d3ec46425e9";
assert_eq!(correct_root_hash, root_hash);
}

0 comments on commit c2e1beb

Please sign in to comment.