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

Use v2::api::Proof<V> over proof::Proof #215

Merged
merged 1 commit into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions firewood/examples/rev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use std::{collections::VecDeque, path::Path};
use firewood::{
db::{BatchOp, Db, DbConfig, Proposal, Revision, WalConfig},
merkle::{Node, TrieHash},
proof::Proof,
storage::StoreRevShared,
v2::api::Proof,
};
use shale::compact::CompactSpace;

Expand Down Expand Up @@ -166,7 +166,7 @@ impl RevisionTracker {
}
}

fn build_proof(revision: &Revision<SharedStore>, items: &[(&str, &str)]) -> Proof {
fn build_proof(revision: &Revision<SharedStore>, items: &[(&str, &str)]) -> Proof<Vec<u8>> {
let mut proof = revision.prove(items[0].0).unwrap();
let end = revision.prove(items.last().unwrap().0).unwrap();
proof.concat_proofs(end);
Expand Down
12 changes: 6 additions & 6 deletions firewood/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ pub use crate::{
use crate::{
file,
merkle::{Merkle, MerkleError, Node, TrieHash, TRIE_HASH_LEN},
proof::{Proof, ProofError},
proof::ProofError,
storage::{
buffer::{BufferWrite, DiskBuffer, DiskBufferRequester},
AshRecord, CachedSpace, MemStoreR, SpaceWrite, StoreConfig, StoreDelta, StoreRevMut,
StoreRevShared, ZeroStore, PAGE_SIZE_NBIT,
},
v2::api::Proof,
};
use bytemuck::{cast_slice, AnyBitPattern};
use metered::{metered, HitCount};
Expand Down Expand Up @@ -313,15 +314,14 @@ impl<S: ShaleStore<Node> + Send + Sync> DbRev<S> {
.map_err(DbError::Merkle)
}

/// Provides a proof that a key is in the Trie.
pub fn prove<K: AsRef<[u8]>>(&self, key: K) -> Result<Proof, MerkleError> {
self.merkle.prove(key, self.header.kv_root)
pub fn prove<K: AsRef<[u8]>>(&self, key: K) -> Result<Proof<Vec<u8>>, MerkleError> {
self.merkle.prove::<K>(key, self.header.kv_root)
}

/// Verifies a range proof is valid for a set of keys.
pub fn verify_range_proof<K: AsRef<[u8]>, V: AsRef<[u8]>>(
pub fn verify_range_proof<N: AsRef<[u8]> + Send, K: AsRef<[u8]>, V: AsRef<[u8]>>(
&self,
proof: Proof,
proof: Proof<N>,
first_key: K,
last_key: K,
keys: Vec<K>,
Expand Down
6 changes: 3 additions & 3 deletions firewood/src/merkle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE.md for licensing terms.

use crate::{nibbles::Nibbles, proof::Proof};
use crate::{nibbles::Nibbles, v2::api::Proof};
use sha3::Digest;
use shale::{disk_address::DiskAddress, ObjRef, ShaleError, ShaleStore};
use std::{
Expand Down Expand Up @@ -1031,13 +1031,13 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
/// If the trie does not contain a value for key, the returned proof contains
/// all nodes of the longest existing prefix of the key, ending with the node
/// that proves the absence of the key (at least the root node).
pub fn prove<K: AsRef<[u8]>>(&self, key: K, root: DiskAddress) -> Result<Proof, MerkleError>
pub fn prove<K>(&self, key: K, root: DiskAddress) -> Result<Proof<Vec<u8>>, MerkleError>
where
K: AsRef<[u8]>,
{
let key_nibbles = Nibbles::<0>::new(key.as_ref());

let mut proofs: HashMap<[u8; TRIE_HASH_LEN], Vec<u8>> = HashMap::new();
let mut proofs = HashMap::new();
if root.is_null() {
return Ok(Proof(proofs));
}
Expand Down
13 changes: 7 additions & 6 deletions firewood/src/merkle_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

use crate::{
merkle::{Merkle, Node, Ref, RefMut, TrieHash},
proof::{Proof, ProofError},
proof::ProofError,
v2::api::Proof,
};
use shale::{
cached::DynamicMem, compact::CompactSpace, disk_address::DiskAddress, CachedStore, ShaleStore,
Expand Down Expand Up @@ -86,26 +87,26 @@ impl<S: ShaleStore<Node> + Send + Sync> MerkleSetup<S> {
String::from_utf8(s).map_err(|_err| DataStoreError::UTF8Error)
}

pub fn prove<K: AsRef<[u8]>>(&self, key: K) -> Result<Proof, DataStoreError> {
pub fn prove<K: AsRef<[u8]>>(&self, key: K) -> Result<Proof<Vec<u8>>, DataStoreError> {
self.merkle
.prove(key, self.root)
.map_err(|_err| DataStoreError::ProofError)
}

pub fn verify_proof<K: AsRef<[u8]>>(
pub fn verify_proof<N: AsRef<[u8]> + Send, K: AsRef<[u8]>>(
&self,
key: K,
proof: &Proof,
proof: &Proof<N>,
) -> Result<Option<Vec<u8>>, DataStoreError> {
let hash: [u8; 32] = *self.root_hash()?;
proof
.verify_proof(key, hash)
.map_err(|_err| DataStoreError::ProofVerificationError)
}

pub fn verify_range_proof<K: AsRef<[u8]>, V: AsRef<[u8]>>(
pub fn verify_range_proof<N: AsRef<[u8]> + Send, K: AsRef<[u8]>, V: AsRef<[u8]>>(
&self,
proof: &Proof,
proof: &Proof<N>,
first_key: K,
last_key: K,
keys: Vec<K>,
Expand Down
34 changes: 20 additions & 14 deletions firewood/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ use crate::{
merkle_util::{new_merkle, DataStoreError, MerkleSetup},
};
use nix::errno::Errno;
use serde::{Deserialize, Serialize};
use sha3::Digest;
use shale::{disk_address::DiskAddress, ShaleError, ShaleStore};
use std::{cmp::Ordering, collections::HashMap, error::Error, fmt, ops::Deref};
use shale::disk_address::DiskAddress;
use shale::ShaleError;
use shale::ShaleStore;

/// Hash -> RLP encoding map
#[derive(Debug, Serialize, Deserialize)]
pub struct Proof(pub HashMap<[u8; 32], Vec<u8>>);
use std::cmp::Ordering;
use std::error::Error;
use std::fmt;
use std::ops::Deref;

use crate::v2::api::Proof;

#[derive(Debug)]
pub enum ProofError {
Expand Down Expand Up @@ -116,10 +119,12 @@ pub struct SubProof {
hash: Option<[u8; 32]>,
}

impl Proof {
impl<N: AsRef<[u8]> + Send> Proof<N> {
/// verify_proof checks merkle proofs. The given proof must contain the value for
/// key in a trie with the given root hash. VerifyProof returns an error if the
/// proof contains invalid trie nodes or the wrong value.
///
/// The generic N represents the storage for the node data
pub fn verify_proof<K: AsRef<[u8]>>(
&self,
key: K,
Expand All @@ -137,7 +142,8 @@ impl Proof {
let cur_proof = proofs_map
.get(&cur_hash)
.ok_or(ProofError::ProofNodeMissing)?;
let (sub_proof, size) = self.locate_subproof(remaining_key_nibbles, cur_proof)?;
let (sub_proof, size) =
self.locate_subproof(remaining_key_nibbles, cur_proof.as_ref())?;
index += size;

match sub_proof {
Expand Down Expand Up @@ -242,7 +248,7 @@ impl Proof {
}
}

pub fn concat_proofs(&mut self, other: Proof) {
pub fn concat_proofs(&mut self, other: Proof<N>) {
self.0.extend(other.0)
}

Expand Down Expand Up @@ -290,7 +296,7 @@ impl Proof {
// ensure there are no more accounts / slots in the trie.
if keys.is_empty() {
let proof_to_path =
self.proof_to_path(first_key.as_ref(), root_hash, &mut merkle_setup, true)?;
self.proof_to_path(first_key, root_hash, &mut merkle_setup, true)?;
return match proof_to_path {
Some(_) => Err(ProofError::InvalidData),
None => Ok(false),
Expand Down Expand Up @@ -365,9 +371,9 @@ impl Proof {
/// necessary nodes will be resolved and leave the remaining as hashnode.
///
/// The given edge proof is allowed to be an existent or non-existent proof.
fn proof_to_path<K: AsRef<[u8]>, S: ShaleStore<Node> + Send + Sync>(
fn proof_to_path<KV: AsRef<[u8]>, S: ShaleStore<Node> + Send + Sync>(
&self,
key: K,
key: KV,
root_hash: [u8; 32],
merkle_setup: &mut MerkleSetup<S>,
allow_non_existent_node: bool,
Expand All @@ -392,7 +398,7 @@ impl Proof {
.ok_or(ProofError::ProofNodeMissing)?;
// TODO(Hao): (Optimization) If a node is alreay decode we don't need to decode again.
let (mut chd_ptr, sub_proof, size) =
self.decode_node(merkle, cur_key, cur_proof, false)?;
self.decode_node(merkle, cur_key, cur_proof.as_ref(), false)?;

// Link the child to the parent based on the node type.
match &u_ref.inner() {
Expand Down Expand Up @@ -464,7 +470,7 @@ impl Proof {
let proof =
proofs_map.get(p_hash).ok_or(ProofError::ProofNodeMissing)?;

chd_ptr = self.decode_node(merkle, cur_key, proof, true)?.0;
chd_ptr = self.decode_node(merkle, cur_key, proof.as_ref(), true)?.0;

// Link the child to the parent based on the node type.
match &u_ref.inner() {
Expand Down
4 changes: 3 additions & 1 deletion firewood/src/v2/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ pub struct RangeProof<K: KeyType, V: ValueType> {
}

/// A proof that a single key is present
///
/// The generic N represents the storage for the node data
#[derive(Debug)]
pub struct Proof<V>(pub HashMap<HashKey, V>);
pub struct Proof<N: Send>(pub HashMap<HashKey, N>);

/// The database interface, which includes a type for a static view of
/// the database (the DbView). The most common implementation of the DbView
Expand Down
2 changes: 1 addition & 1 deletion firewood/tests/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ fn create_db_issue_proof() {
let key = "doe".as_bytes();
let root_hash = rev.kv_root_hash();

match rev.prove(key) {
match rev.prove::<&[u8]>(key) {
Ok(proof) => {
let verification = proof.verify_proof(key, *root_hash.unwrap()).unwrap();
assert!(verification.is_some());
Expand Down
5 changes: 3 additions & 2 deletions firewood/tests/merkle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use firewood::{
merkle::Node,
merkle_util::{new_merkle, DataStoreError, MerkleSetup},
proof::{Proof, ProofError},
proof::ProofError,
v2::api::Proof,
};
use rand::Rng;
use shale::{cached::DynamicMem, compact::CompactSpace};
Expand Down Expand Up @@ -679,7 +680,7 @@ fn test_all_elements_proof() -> Result<(), ProofError> {
let keys: Vec<&[u8; 32]> = item_iter.clone().map(|item| item.0).collect();
let vals: Vec<&[u8; 20]> = item_iter.map(|item| item.1).collect();

let empty_proof = Proof(HashMap::new());
let empty_proof = Proof(HashMap::<[u8; 32], Vec<u8>>::new());
let empty_key: [u8; 32] = [0; 32];
merkle.verify_range_proof(
&empty_proof,
Expand Down
Loading