From 2a6f1abea7bec5115e7c39940e449606fb03bdae Mon Sep 17 00:00:00 2001 From: Evgeny Fomin Date: Wed, 14 Aug 2024 16:13:23 +0200 Subject: [PATCH] reference insertion fixes --- grovedb/src/element/mod.rs | 11 ++++ grovedb/src/lib.rs | 4 +- grovedb/src/operations/insert/mod.rs | 81 +++++----------------------- grovedb/src/tests/mod.rs | 28 +++++----- 4 files changed, 39 insertions(+), 85 deletions(-) diff --git a/grovedb/src/element/mod.rs b/grovedb/src/element/mod.rs index ad2540e3..11089a9c 100644 --- a/grovedb/src/element/mod.rs +++ b/grovedb/src/element/mod.rs @@ -16,6 +16,9 @@ pub(crate) mod helpers; mod insert; #[cfg(any(feature = "full", feature = "verify"))] mod query; +use grovedb_costs::{cost_return_on_error_default, CostContext, CostsExt, OperationCost}; +use grovedb_merk::{tree::value_hash, CryptoHash}; +use grovedb_version::version::GroveVersion; #[cfg(any(feature = "full", feature = "verify"))] pub use query::QueryOptions; #[cfg(any(feature = "full", feature = "verify"))] @@ -153,6 +156,14 @@ impl Element { Element::SumTree(..) => "sum tree", } } + + pub(crate) fn value_hash( + &self, + grove_version: &GroveVersion, + ) -> CostContext> { + let bytes = cost_return_on_error_default!(self.serialize(grove_version)); + value_hash(&bytes).map(Result::Ok) + } } #[cfg(any(feature = "full", feature = "visualize"))] diff --git a/grovedb/src/lib.rs b/grovedb/src/lib.rs index 0c15d0c9..96c2d0de 100644 --- a/grovedb/src/lib.rs +++ b/grovedb/src/lib.rs @@ -1077,7 +1077,7 @@ impl GroveDb { grove_version, ) .unwrap()?; - value_hash(&item.serialize(grove_version)?).unwrap() + item.value_hash(grove_version).unwrap()? }; // Take the current item (reference) hash and combine it with referenced value's @@ -1217,7 +1217,7 @@ impl GroveDb { grove_version, ) .unwrap()?; - value_hash(&item.serialize(grove_version)?).unwrap() + item.value_hash(grove_version).unwrap()? }; // Take the current item (reference) hash and combine it with referenced value's diff --git a/grovedb/src/operations/insert/mod.rs b/grovedb/src/operations/insert/mod.rs index b7e00fc1..87f0f97b 100644 --- a/grovedb/src/operations/insert/mod.rs +++ b/grovedb/src/operations/insert/mod.rs @@ -7,6 +7,7 @@ use std::{collections::HashMap, option::Option::None}; use grovedb_costs::{ cost_return_on_error, cost_return_on_error_no_add, CostResult, CostsExt, OperationCost, }; +use grovedb_merk::tree::value_hash; #[cfg(feature = "full")] use grovedb_merk::{tree::NULL_HASH, Merk, MerkOptions}; use grovedb_path::SubtreePath; @@ -293,44 +294,18 @@ impl GroveDb { .wrap_with_cost(OperationCost::default()) ); - let (referenced_key, referenced_path) = reference_path.split_last().unwrap(); - let subtree_for_reference = cost_return_on_error!( + let referenced_item = cost_return_on_error!( &mut cost, - self.open_transactional_merk_at_path( - referenced_path.into(), - transaction, - Some(batch), - grove_version, - ) - ); - - let referenced_element_value_hash_opt = cost_return_on_error!( - &mut cost, - Element::get_value_hash( - &subtree_for_reference, - referenced_key, - true, + self.follow_reference( + reference_path.as_slice().into(), + false, + Some(transaction), grove_version ) ); - let referenced_element_value_hash = cost_return_on_error!( - &mut cost, - referenced_element_value_hash_opt - .ok_or({ - let reference_string = reference_path - .iter() - .map(hex::encode) - .collect::>() - .join("/"); - Error::MissingReference(format!( - "reference {}/{} can not be found", - reference_string, - hex::encode(key) - )) - }) - .wrap_with_cost(OperationCost::default()) - ); + let referenced_element_value_hash = + cost_return_on_error!(&mut cost, referenced_item.value_hash(grove_version)); cost_return_on_error!( &mut cost, @@ -452,46 +427,18 @@ impl GroveDb { path_from_reference_path_type(reference_path.clone(), path, Some(key)) .wrap_with_cost(OperationCost::default()) ); - - // TODO unwrap? - let (referenced_key, referenced_path) = reference_path.split_last().unwrap(); - let subtree_for_reference = cost_return_on_error!( + let referenced_item = cost_return_on_error!( &mut cost, - self.open_non_transactional_merk_at_path( - referenced_path.into(), - Some(batch), - grove_version - ) - ); - - // when there is no transaction, we don't want to use caching - let referenced_element_value_hash_opt = cost_return_on_error!( - &mut cost, - Element::get_value_hash( - &subtree_for_reference, - referenced_key, + self.follow_reference( + reference_path.as_slice().into(), false, + None, grove_version ) ); - let referenced_element_value_hash = cost_return_on_error!( - &mut cost, - referenced_element_value_hash_opt - .ok_or({ - let reference_string = reference_path - .iter() - .map(hex::encode) - .collect::>() - .join("/"); - Error::MissingReference(format!( - "reference {}/{} can not be found", - reference_string, - hex::encode(key) - )) - }) - .wrap_with_cost(OperationCost::default()) - ); + let referenced_element_value_hash = + cost_return_on_error!(&mut cost, referenced_item.value_hash(grove_version)); cost_return_on_error!( &mut cost, diff --git a/grovedb/src/tests/mod.rs b/grovedb/src/tests/mod.rs index fa48a900..f6b7b6d4 100644 --- a/grovedb/src/tests/mod.rs +++ b/grovedb/src/tests/mod.rs @@ -1190,7 +1190,12 @@ mod tests { ) .unwrap(); - assert!(matches!(result, Err(Error::MissingReference(_)))); + dbg!(&result); + + assert!(matches!( + result, + Err(Error::CorruptedReferencePathKeyNotFound(_)) + )); } #[test] @@ -1229,24 +1234,15 @@ mod tests { } // Add one more reference - db.insert( - [TEST_LEAF].as_ref(), - &keygen(MAX_REFERENCE_HOPS + 1), - Element::new_reference(ReferencePathType::AbsolutePathReference(vec![ - TEST_LEAF.to_vec(), - keygen(MAX_REFERENCE_HOPS), - ])), - None, - None, - grove_version, - ) - .unwrap() - .expect("expected insert"); - let result = db - .get( + .insert( [TEST_LEAF].as_ref(), &keygen(MAX_REFERENCE_HOPS + 1), + Element::new_reference(ReferencePathType::AbsolutePathReference(vec![ + TEST_LEAF.to_vec(), + keygen(MAX_REFERENCE_HOPS), + ])), + None, None, grove_version, )