Skip to content

Commit

Permalink
Fix proof data update in corner cases. (#13)
Browse files Browse the repository at this point in the history
* Fix proof data update in corner cases.

* Fix fmt.
  • Loading branch information
peilun-conflux authored Jan 28, 2024
1 parent a4abe2b commit 19d9d31
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 7 deletions.
15 changes: 10 additions & 5 deletions common/append_merkle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
mut tx_merkle_nodes: Vec<(usize, E)>,
start_index: u64,
) -> Result<()> {
let tx_merkle_nodes_size = tx_merkle_nodes.len();
if self.leaf_height != 0 {
tx_merkle_nodes = tx_merkle_nodes
.into_iter()
Expand All @@ -228,7 +229,8 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
if tx_merkle_nodes.is_empty() {
return Ok(());
}
let mut position_and_data = proof.file_proof_nodes_in_tree(tx_merkle_nodes);
let mut position_and_data =
proof.file_proof_nodes_in_tree(tx_merkle_nodes, tx_merkle_nodes_size);
let start_index = (start_index >> self.leaf_height) as usize;
for (i, (position, _)) in position_and_data.iter_mut().enumerate() {
*position += start_index >> i;
Expand All @@ -253,10 +255,13 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
continue;
}
if layer[position] != E::null() && layer[position] != data {
// This is possible for a valid file proof only when the file proof node is an intermediate node,
// so the correct proof node in the flow merkle tree must have been computed as we pad rear data.
// Thus, it's okay to skip this case directly.
continue;
bail!(
"conflict data layer={} position={} tree_data={:?} proof_data={:?}",
i,
position,
layer[position],
data
);
}
layer[position] = data;
}
Expand Down
20 changes: 18 additions & 2 deletions common/append_merkle/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,38 @@ impl<T: HashElement> Proof<T> {
r
}

pub fn file_proof_nodes_in_tree(&self, tx_merkle_nodes: Vec<(usize, T)>) -> Vec<(usize, T)> {
pub fn file_proof_nodes_in_tree(
&self,
tx_merkle_nodes: Vec<(usize, T)>,
tx_merkle_nodes_size: usize,
) -> Vec<(usize, T)> {
let mut r = Vec::with_capacity(self.lemma.len());
let mut subtree_pos = 0;
let mut root_pos = 0;
let mut in_subtree = tx_merkle_nodes.len() == 1;
let mut in_subtree = tx_merkle_nodes_size == 1;
for (i, is_left) in self.path.iter().rev().enumerate() {
if !in_subtree {
if *is_left {
in_subtree = true;
root_pos >>= tx_merkle_nodes[i].0;
} else if i < tx_merkle_nodes.len() {
root_pos += 1 << tx_merkle_nodes[i].0;

// This is the last node, so there is no more intermediate node.
if i == tx_merkle_nodes_size - 2 {
if i + 1 >= tx_merkle_nodes.len() {
break;
} else {
in_subtree = true;
root_pos >>= tx_merkle_nodes[i + 1].0;
}
}
} else {
break;
}
} else {
subtree_pos <<= 1;
root_pos <<= 1;
if !*is_left {
subtree_pos += 1;
}
Expand Down

0 comments on commit 19d9d31

Please sign in to comment.