Skip to content
Draft
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
54 changes: 54 additions & 0 deletions rs_zktrie/src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,60 @@ impl<H: Hashable, DB: ZktrieDatabase, const MAX_LEVELS: usize> ZkTrieImpl<H, DB,
}
}

/// prove soft constructs a merkle proof like prove, but end at the node ABOVE
/// terminal node, since terminal node maybe not accessable without deletion proof
/// currently it is used by ccc
pub fn prove_soft(&self, node_key: &H) -> Result<Vec<Node<H>>, ImplError> {
let path = Self::get_path(node_key);
let mut next_hash = self.root_hash.clone();
let mut nodes = Vec::with_capacity(MAX_LEVELS);
for p in path.iter() {
let n = self.get_node(&next_hash)?;
let finished = match n.node_type {
NodeTypeEmptyNew | NodeTypeLeafNew => {
// the only possible to encounter this node
return Ok(Vec::new())
},
// both terminal
NodeTypeBranch0 => true,
// left (*p == 0) is terminal
NodeTypeBranch1 => if *p {
next_hash = n.child_right.clone().expect("node should has this child");
false
} else {
true
}
// right (*p == 1) is terminal
NodeTypeBranch2 => if *p {
true
} else {
next_hash = n.child_left.clone().expect("node should has this child");
false
}
// both are not terminal
NodeTypeBranch3 => {
if *p {
next_hash = n.child_right.clone().expect("node should has this child");
} else {
next_hash = n.child_left.clone().expect("node should has this child");
};
false
}
NodeTypeEmpty | NodeTypeLeaf | NodeTypeParent => {
unreachable!("encounter deprecated node types")
}
_ => unreachable!(),
};

nodes.push(n);
if finished {
break;
}
}

Ok(nodes)
}

// prove constructs a merkle proof for SMT, it respect the protocol used by the ethereum-trie
// but save the node data with a compact form
pub fn prove(&self, node_key: &H) -> Result<Vec<Node<H>>, ImplError> {
Expand Down
13 changes: 11 additions & 2 deletions rs_zktrie/src/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,18 @@ impl<H: Hashable, DB: ZktrieDatabase + KeyCache<H>> ZkTrie<H, DB> {
// tuple is false
//
// If the trie contain a non-empty leaf for key, the `bool` in returned tuple is true
pub fn prove(&self, key_hash_byte: &[u8]) -> Result<(Vec<Node<H>>, bool), ImplError> {
pub fn prove(&self, key_hash_byte: &[u8], is_soft: bool) -> Result<(Vec<Node<H>>, bool), ImplError> {
let key_hash = H::from_bytes(key_hash_byte)?;
let proof = self.tree.prove(&key_hash)?;
let proof = if is_soft {
self.tree.prove_soft(&key_hash)
.map(|mut proof|{
// add a dummy leaf node to keep the consistent of format
proof.push(Node::new_empty_node());
proof
})
} else {
self.tree.prove(&key_hash)
}?;
let mut hit = false;

for n in &proof {
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ mod tests {
Rc::get_mut(&mut db).expect("no reference").update(trie_db);
let trie = db.new_ref_trie(&root).unwrap();

let proof = trie.prove(&acc_buf).unwrap();
let proof = trie.prove(&acc_buf, false).unwrap();

assert_eq!(proof.len(), 8);
assert_eq!(proof[7], hex::decode("5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449").unwrap());
Expand Down
4 changes: 2 additions & 2 deletions src/rs_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,12 @@ impl<DB: db::ZktrieDatabase + trie::KeyCache<HashImpl>> ZkTrie<DB> {
}

// build prove array for mpt path
pub fn prove(&self, key: &[u8]) -> Result<Vec<Vec<u8>>, ErrString> {
pub fn prove(&self, key: &[u8], is_soft: bool) -> Result<Vec<Vec<u8>>, ErrString> {
use types::Node;

let s_key = Node::<HashImpl>::hash_bytes(key).map_err(|e| e.to_string())?;

let (proof, _) = self.0.prove(s_key.as_ref()).map_err(|e| e.to_string())?;
let (proof, _) = self.0.prove(s_key.as_ref(), is_soft).map_err(|e| e.to_string())?;

Ok(proof
.into_iter()
Expand Down