diff --git a/grovedb/src/lib.rs b/grovedb/src/lib.rs index 94464040d..b8f46009d 100644 --- a/grovedb/src/lib.rs +++ b/grovedb/src/lib.rs @@ -9,12 +9,9 @@ use std::{ }; pub use merk::proofs::{query::QueryItem, Query}; -use merk::{ - self, - proofs::query::Map, - Merk, -}; +use merk::{self, proofs::query::Map, Merk}; use rs_merkle::{algorithms::Sha256, Hasher, MerkleProof, MerkleTree}; +use serde::{Deserialize, Serialize}; use storage::{ rocksdb_storage::{PrefixedRocksDbStorage, PrefixedRocksDbStorageError}, Storage, @@ -47,13 +44,14 @@ pub enum Error { CorruptedData(String), } -pub struct ProofQuery<'a> { +pub struct PathQuery<'a> { path: &'a [&'a [u8]], query: Query, } -pub struct Proof<'a> { - query_paths: Vec<&'a [&'a [u8]]>, +#[derive(Serialize, Deserialize)] +pub struct Proof { + query_paths: Vec>>, proofs: HashMap, Vec>, root_proof: Vec, root_leaf_keys: HashMap, usize>, @@ -301,7 +299,7 @@ impl GroveDb { Err(Error::ReferenceLimit) } - pub fn proof<'a>(&mut self, proof_queries: Vec>) -> Result, Error> { + pub fn proof(&mut self, proof_queries: Vec) -> Result, Error> { // To prove a path we need to return a proof for each node on the path including // the root. With multiple paths, nodes can overlap i.e two or more paths can // share the same nodes. We should only have one proof for each node, @@ -315,7 +313,13 @@ impl GroveDb { // For each unique node including the root // determine what keys would need to be included in the proof for proof_query in proof_queries { - query_paths.push(proof_query.path); + query_paths.push( + proof_query + .path + .iter() + .map(|x| x.to_vec()) + .collect::>(), + ); let compressed_path = GroveDb::compress_subtree_key(proof_query.path, None); proof_spec.insert(compressed_path, proof_query.query); @@ -357,12 +361,17 @@ impl GroveDb { } let root_proof = self.root_tree.proof(&root_index).to_bytes(); - Ok(Proof { + let proof = Proof { query_paths, proofs, root_proof, root_leaf_keys: self.root_leaf_keys.clone(), - }) + }; + + let seralized_proof = bincode::serialize(&proof) + .map_err(|_| Error::CorruptedData(String::from("unable to serialize proof")))?; + + Ok(seralized_proof) } fn prove_item(&self, path: &Vec, proof_query: Query) -> Result, Error> { @@ -378,7 +387,11 @@ impl GroveDb { Ok(proof_result) } - pub fn execute_proof(proof: Proof) -> Result<([u8; 32], HashMap, Map>), Error> { + pub fn execute_proof(proof: Vec) -> Result<([u8; 32], HashMap, Map>), Error> { + // Deserialize the proof + let proof: Proof = bincode::deserialize(&proof) + .map_err(|_| Error::CorruptedData(String::from("unable to deserialize proof")))?; + // Required to execute the root proof let mut root_keys_index: Vec = Vec::new(); let mut root_hashes: Vec<[u8; 32]> = Vec::new(); @@ -387,12 +400,13 @@ impl GroveDb { let mut result_map: HashMap, Map> = HashMap::new(); for path in proof.query_paths { + let path = path.iter().map(|x| x.as_slice()).collect::>(); // For each query path, get the result map after execution // and store hash + index for later root proof execution - let root_key = path[0]; - let (hash, proof_result_map) = GroveDb::execute_path(path, &proof.proofs)?; + let root_key = &path[0]; + let (hash, proof_result_map) = GroveDb::execute_path(&path, &proof.proofs)?; let compressed_root_key_path = GroveDb::compress_subtree_key(&[], Some(&root_key)); - let compressed_query_path = GroveDb::compress_subtree_key(path, None); + let compressed_query_path = GroveDb::compress_subtree_key(&path, None); let index = proof .root_leaf_keys diff --git a/grovedb/src/tests.rs b/grovedb/src/tests.rs index 4c9da3c8f..b68bd14c4 100644 --- a/grovedb/src/tests.rs +++ b/grovedb/src/tests.rs @@ -356,21 +356,24 @@ fn test_proof_construction() { // Get grovedb proof let proof = temp_db .proof(vec![ - ProofQuery { + PathQuery { path: &[TEST_LEAF, b"innertree"], query: path_one_query, }, - ProofQuery { + PathQuery { path: &[ANOTHER_TEST_LEAF, b"innertree3"], query: path_two_query, }, - ProofQuery { + PathQuery { path: &[ANOTHER_TEST_LEAF, b"innertree2"], query: path_three_query, }, ]) .unwrap(); + // Deserialize the proof + let proof: Proof = bincode::deserialize(&proof).unwrap(); + // Perform assertions assert_eq!(proof.query_paths.len(), 3); assert_eq!(proof.query_paths[0], &[TEST_LEAF, b"innertree"]); @@ -386,9 +389,10 @@ fn test_proof_construction() { // Check that all the subproofs were constructed correctly for each path and // subpath - let path_one_as_vec = GroveDb::compress_subtree_key(proof.query_paths[0], None); - let path_two_as_vec = GroveDb::compress_subtree_key(proof.query_paths[1], None); - let path_three_as_vec = GroveDb::compress_subtree_key(proof.query_paths[2], None); + let path_one_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF, b"innertree"], None); + let path_two_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree3"], None); + let path_three_as_vec = + GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree2"], None); let test_leaf_path_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF], None); let another_test_leaf_path_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF], None); @@ -527,7 +531,7 @@ fn test_successful_proof_verification() { path_one_query.insert_key(b"key2".to_vec()); let proof = temp_db - .proof(vec![ProofQuery { + .proof(vec![PathQuery { path: &[TEST_LEAF, b"innertree"], query: path_one_query, }]) @@ -556,11 +560,11 @@ fn test_successful_proof_verification() { // Get grovedb proof let proof = temp_db .proof(vec![ - ProofQuery { + PathQuery { path: &[ANOTHER_TEST_LEAF, b"innertree3"], query: path_two_query, }, - ProofQuery { + PathQuery { path: &[ANOTHER_TEST_LEAF, b"innertree2"], query: path_three_query, },