Skip to content

Commit

Permalink
reference insertion fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
fominok committed Aug 14, 2024
1 parent 35a97e1 commit 2a6f1ab
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 85 deletions.
11 changes: 11 additions & 0 deletions grovedb/src/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Check warning on line 19 in grovedb/src/element/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `CostsExt`

warning: unused import: `CostsExt` --> grovedb/src/element/mod.rs:19:64 | 19 | 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"))]
Expand Down Expand Up @@ -153,6 +156,14 @@ impl Element {
Element::SumTree(..) => "sum tree",
}
}

pub(crate) fn value_hash(
&self,
grove_version: &GroveVersion,
) -> CostContext<Result<CryptoHash, crate::Error>> {
let bytes = cost_return_on_error_default!(self.serialize(grove_version));
value_hash(&bytes).map(Result::Ok)
}
}

#[cfg(any(feature = "full", feature = "visualize"))]
Expand Down
4 changes: 2 additions & 2 deletions grovedb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
81 changes: 14 additions & 67 deletions grovedb/src/operations/insert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Check warning on line 10 in grovedb/src/operations/insert/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `grovedb_merk::tree::value_hash`

warning: unused import: `grovedb_merk::tree::value_hash` --> grovedb/src/operations/insert/mod.rs:10:5 | 10 | use grovedb_merk::tree::value_hash; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
#[cfg(feature = "full")]
use grovedb_merk::{tree::NULL_HASH, Merk, MerkOptions};
use grovedb_path::SubtreePath;
Expand Down Expand Up @@ -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::<Vec<String>>()
.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,
Expand Down Expand Up @@ -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::<Vec<String>>()
.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,
Expand Down
28 changes: 12 additions & 16 deletions grovedb/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,12 @@ mod tests {
)
.unwrap();

assert!(matches!(result, Err(Error::MissingReference(_))));
dbg!(&result);

assert!(matches!(
result,
Err(Error::CorruptedReferencePathKeyNotFound(_))
));
}

#[test]
Expand Down Expand Up @@ -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,
)
Expand Down

0 comments on commit 2a6f1ab

Please sign in to comment.