Fix proof data update in corner cases. (#13)

* Fix proof data update in corner cases.

* Fix fmt.
This commit is contained in:
peilun-conflux 2024-01-28 16:52:28 +08:00 committed by GitHub
parent a4abe2b2a4
commit 19d9d31b0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 7 deletions

View File

@ -213,6 +213,7 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
mut tx_merkle_nodes: Vec<(usize, E)>, mut tx_merkle_nodes: Vec<(usize, E)>,
start_index: u64, start_index: u64,
) -> Result<()> { ) -> Result<()> {
let tx_merkle_nodes_size = tx_merkle_nodes.len();
if self.leaf_height != 0 { if self.leaf_height != 0 {
tx_merkle_nodes = tx_merkle_nodes tx_merkle_nodes = tx_merkle_nodes
.into_iter() .into_iter()
@ -228,7 +229,8 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
if tx_merkle_nodes.is_empty() { if tx_merkle_nodes.is_empty() {
return Ok(()); 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; let start_index = (start_index >> self.leaf_height) as usize;
for (i, (position, _)) in position_and_data.iter_mut().enumerate() { for (i, (position, _)) in position_and_data.iter_mut().enumerate() {
*position += start_index >> i; *position += start_index >> i;
@ -253,10 +255,13 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
continue; continue;
} }
if layer[position] != E::null() && layer[position] != data { 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, bail!(
// so the correct proof node in the flow merkle tree must have been computed as we pad rear data. "conflict data layer={} position={} tree_data={:?} proof_data={:?}",
// Thus, it's okay to skip this case directly. i,
continue; position,
layer[position],
data
);
} }
layer[position] = data; layer[position] = data;
} }

View File

@ -103,22 +103,38 @@ impl<T: HashElement> Proof<T> {
r 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 r = Vec::with_capacity(self.lemma.len());
let mut subtree_pos = 0; let mut subtree_pos = 0;
let mut root_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() { for (i, is_left) in self.path.iter().rev().enumerate() {
if !in_subtree { if !in_subtree {
if *is_left { if *is_left {
in_subtree = true; in_subtree = true;
root_pos >>= tx_merkle_nodes[i].0;
} else if i < tx_merkle_nodes.len() { } else if i < tx_merkle_nodes.len() {
root_pos += 1 << tx_merkle_nodes[i].0; 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 { } else {
break; break;
} }
} else { } else {
subtree_pos <<= 1; subtree_pos <<= 1;
root_pos <<= 1;
if !*is_left { if !*is_left {
subtree_pos += 1; subtree_pos += 1;
} }