Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support tombstone'd value states in the storage-layer #161

Merged
merged 21 commits into from
Mar 15, 2022
Merged
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a89c3c6
Adjust the public crate-level types which are commonly utilized by cl…
slawlor Mar 1, 2022
da46f91
Move AkdValue and AkdLabel to binary vectors instead of strings
slawlor Mar 1, 2022
9b70b8a
Identify tombstones in client & add flag to support them, verificatio…
slawlor Mar 2, 2022
e7304bd
Tombstoning at the storage layer
slawlor Mar 2, 2022
bbd08a5
Verify the hash of the plaintext value compared to the hash in the ex…
slawlor Mar 2, 2022
8f3fe03
Adding test coverage around tombstoned entries in the key history.
slawlor Mar 2, 2022
6593253
Debugging statements and rustfmt + clippy
slawlor Mar 3, 2022
08aac53
CI clippy
slawlor Mar 3, 2022
93052d1
Cleanup of leaf hashing logic
slawlor Mar 3, 2022
1b12ba2
Merge remote-tracking branch 'origin/main' into slawlor/tombstone
slawlor Mar 8, 2022
767fc63
PR review
slawlor Mar 8, 2022
16fd61f
Clippy still failing client-side on Mac, so fixing CI indentified cli…
slawlor Mar 8, 2022
e94515c
Merge remote-tracking branch 'origin/main' into slawlor/tombstone
slawlor Mar 8, 2022
7e53143
Merge remote-tracking branch 'origin/main' into slawlor/tombstone
slawlor Mar 9, 2022
74ca391
merge clippy's
slawlor Mar 9, 2022
5bf7b21
rustfmt after clippy :sad_eyes:
slawlor Mar 9, 2022
d0dca50
PR review: move tombstone to empty array of data and add more test co…
slawlor Mar 9, 2022
744b9d1
Merge remote-tracking branch 'origin/main' into slawlor/tombstone
slawlor Mar 10, 2022
458648b
Addressing: #170. Adding a top N key updates to the history call.
slawlor Mar 10, 2022
48fdb3f
clippy lint caught in CI
slawlor Mar 10, 2022
0ab1408
Merge remote-tracking branch 'origin/main' into slawlor/tombstone
slawlor Mar 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'origin/main' into slawlor/tombstone
  • Loading branch information
slawlor committed Mar 10, 2022
commit 744b9d1988f357228acf6bc04e0eb27d8215c426
36 changes: 23 additions & 13 deletions akd/src/directory.rs
Original file line number Diff line number Diff line change
@@ -190,8 +190,8 @@ impl<S: Storage + Sync + Send, V: VRFKeyStorage> Directory<S, V> {

if let false = self.storage.begin_transaction().await {
error!("Transaction is already active");
return Err(AkdError::HistoryTreeNode(HistoryTreeNodeError::Storage(
StorageError::SetData("Transaction is already active".to_string()),
return Err(AkdError::Storage(StorageError::Transaction(
"Transaction is already active".to_string(),
)));
}
info!("Starting database insertion");
@@ -212,9 +212,7 @@ impl<S: Storage + Sync + Send, V: VRFKeyStorage> Directory<S, V> {
if let Err(err) = self.storage.commit_transaction().await {
// ignore any rollback error(s)
let _ = self.storage.rollback_transaction().await;
return Err(AkdError::HistoryTreeNode(HistoryTreeNodeError::Storage(
err,
)));
return Err(AkdError::Storage(err));
} else {
debug!("Transaction committed");
}
@@ -357,10 +355,16 @@ impl<S: Storage + Sync + Send, V: VRFKeyStorage> Directory<S, V> {
{
Err(_) => {
// Need to throw an error
Err(AkdError::Directory(DirectoryError::NonExistentUser(
uname.to_vec(),
epoch,
)))
match std::str::from_utf8(&uname) {
Ok(name) => Err(AkdError::Storage(StorageError::NotFound(format!(
"User {} at epoch {}",
name, epoch
)))),
_ => Err(AkdError::Storage(StorageError::NotFound(format!(
"User {:?} at epoch {}",
uname, epoch
)))),
}
}
Ok(latest_st) => {
// Need to account for the case where the latest state is
@@ -412,10 +416,16 @@ impl<S: Storage + Sync + Send, V: VRFKeyStorage> Directory<S, V> {
}
Ok(HistoryProof { proofs })
} else {
Err(AkdError::Storage(StorageError::NotFound(format!(
"User {} at epoch {}",
username, current_epoch
))))
match std::str::from_utf8(&username) {
Ok(name) => Err(AkdError::Storage(StorageError::NotFound(format!(
"User {} at epoch {}",
name, current_epoch
)))),
_ => Err(AkdError::Storage(StorageError::NotFound(format!(
"User {:?} at epoch {}",
username, current_epoch
)))),
}
}
}

35 changes: 6 additions & 29 deletions akd/src/errors.rs
Original file line number Diff line number Diff line change
@@ -182,18 +182,14 @@ impl fmt::Display for AzksError {
#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug)]
pub enum DirectoryError {
/// Looked up a user not in the directory
NonExistentUser(Vec<u8>, u64),
/// Lookup proof did not verify
VerifyLookupProof(String),
/// Key-History proof did not verify
VerifyKeyHistoryProof(String),
/// Tried to audit an invalid epoch range
InvalidEpoch(String),
/// Error propagation
Storage(StorageError),
/// Error propagation for errors from VRF storage
VRFStorageErr(VRFStorageError),
/// AZKS not found in read-only directory mode
ReadOnlyDirectory(String),
/// The user has no history between the start and ending epochs
NoUpdatesInPeriod(Vec<u8>, u64, u64),
}
@@ -203,25 +199,6 @@ impl std::error::Error for DirectoryError {}
impl fmt::Display for DirectoryError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Storage(storage_error) => {
write!(
f,
"Error with retrieving value from storage: {:?}",
storage_error
)
}
Self::NonExistentUser(uname, ep) => {
if let Ok(str) = std::str::from_utf8(uname) {
write!(f, "The user {} did not exist at the epoch {}", str, ep)
} else {
write!(
f,
"The user 0x{} did not exist at the epoch {}",
hex::encode(uname),
ep
)
}
}
Self::VerifyKeyHistoryProof(err_string) => {
write!(f, "Failed to verify key history {}", err_string)
}
@@ -231,20 +208,20 @@ impl fmt::Display for DirectoryError {
Self::VerifyLookupProof(err_string) => {
write!(f, "Failed to verify lookup proof {}", err_string)
}
Self::VRFStorageErr(err) => {
write!(f, "Encountered a VRF error: {:?}", err)
Self::ReadOnlyDirectory(inner_message) => {
write!(f, "Directory in read-only mode: {}", inner_message)
}
Self::NoUpdatesInPeriod(uname, start, end) => {
if let Ok(str) = std::str::from_utf8(uname) {
write!(
f,
"The user {} had no updated between {} -> {}",
"The user {} had no updates between epochs {} -> {}",
str, start, end
)
} else {
write!(
f,
"The user 0x{} had no updated between {} -> {}",
"The user 0x{} had no updates between epochs {} -> {}",
hex::encode(uname),
start,
end
11 changes: 5 additions & 6 deletions akd/src/history_tree_node.rs
Original file line number Diff line number Diff line change
@@ -433,7 +433,7 @@ impl HistoryTreeNode {

let parent =
&mut HistoryTreeNode::get_from_storage(storage, &NodeKey(self.parent), epoch).await?;
if parent.get_latest_epoch()? < epoch {
if parent.get_latest_epoch() < epoch {
let (_, dir_self, _) = parent.label.get_longest_common_prefix_and_dirs(self.label);
parent
.set_node_child::<_, H>(storage, epoch, dir_self, self)
@@ -840,8 +840,8 @@ pub async fn get_leaf_node<H: Hasher, S: Storage + Sync + Send>(
};

let mut new_state: HistoryNodeState =
HistoryNodeState::new::<H>(NodeStateKey(node.label, birth_epoch))?;
new_state.value = from_digest::<H>(H::merge(&[H::hash(&EMPTY_VALUE), *value]))?;
HistoryNodeState::new::<H>(NodeStateKey(node.label, birth_epoch));
new_state.value = from_digest::<H>(H::merge(&[H::hash(&EMPTY_VALUE), *value]));

set_state_map(storage, new_state).await?;

@@ -883,9 +883,8 @@ pub(crate) async fn get_state_map<S: Storage + Sync + Send>(
node: &HistoryTreeNode,
key: u64,
) -> Result<HistoryNodeState, StorageError> {
if let Ok(DbRecord::HistoryNodeState(state)) = storage
.get::<HistoryNodeState>(&get_state_map_key(node, key))
.await
let state_key = get_state_map_key(node, key);
if let Ok(DbRecord::HistoryNodeState(state)) = storage.get::<HistoryNodeState>(&state_key).await
{
Ok(state)
} else {
8 changes: 4 additions & 4 deletions akd/src/lib.rs
Original file line number Diff line number Diff line change
@@ -329,10 +329,6 @@ pub mod proof_structs;
pub mod serialization;
pub mod storage;

#[cfg(any(test, feature = "public-tests"))]
pub mod test_utils;
#[cfg(test)]
mod tests;
mod utils;

// ========== Type re-exports which are commonly used ========== //
@@ -342,6 +338,10 @@ pub use node_state::{Node, NodeLabel};
pub use storage::types::{AkdLabel, AkdValue};

// ========== Constants and type aliases ========== //
#[cfg(any(test, feature = "public-tests"))]
pub mod test_utils;
#[cfg(test)]
mod tests;

/// The arity of the underlying tree structure of the akd.
pub const ARITY: usize = 2;
4 changes: 2 additions & 2 deletions akd_client/src/tests.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ use alloc::vec;
#[cfg(feature = "nostd")]
use alloc::vec::Vec;

use akd::errors::AkdError;
use akd::errors::{AkdError, StorageError};
use akd::storage::Storage;
use akd::{AkdLabel, AkdValue};

@@ -543,7 +543,7 @@ async fn test_tombstoned_key_history() -> Result<(), AkdError> {
internal_proof,
true,
)
.map_err(|ver_err| AkdError::AzksNotFound(format!("INTERNAL: {}", ver_err)))?;
.map_err(|i_err| AkdError::Storage(StorageError::Other(format!("Internal: {:?}", i_err))))?;

assert_eq!(true, tombstones[0]);
assert_eq!(true, tombstones[1]);
41 changes: 0 additions & 41 deletions akd_mysql/src/mysql_storables.rs
Original file line number Diff line number Diff line change
@@ -450,47 +450,6 @@ impl MySqlStorable for DbRecord {
}
}

fn get_specific_params<St: Storable>(key: &St::Key) -> Option<mysql_async::Params> {
match St::data_type() {
StorageType::Azks => None,
StorageType::HistoryNodeState => {
let bin = St::get_full_binary_key_id(key);

if let Ok(back) = HistoryNodeState::key_from_full_binary(&bin) {
Some(params! {
"label_len" => back.0.len,
"label_val" => back.0.val,
"epoch" => back.1
})
} else {
None
}
}
StorageType::HistoryTreeNode => {
let bin = St::get_full_binary_key_id(key);
if let Ok(back) = HistoryTreeNode::key_from_full_binary(&bin) {
Some(params! {
"label_len" => back.0.len,
"label_val" => back.0.val,
})
} else {
None
}
}
StorageType::ValueState => {
let bin = St::get_full_binary_key_id(key);
if let Ok(back) = akd::storage::types::ValueState::key_from_full_binary(&bin) {
Some(params! {
"username" => back.0,
"epoch" => back.1
})
} else {
None
}
}
}
}

fn from_row<St: Storable>(row: &mut mysql_async::Row) -> core::result::Result<Self, MySqlError>
where
Self: std::marker::Sized,
You are viewing a condensed version of this merge commit. You can view the full changes here.