// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
usesuper::leaf_node::LeafNode; usesuper::node::{LeafIndex, NodeVec}; usesuper::tree_math::BfsIterTopDown; usecrate::client::MlsError; usecrate::crypto::CipherSuiteProvider; usecrate::tree_kem::math as tree_math; usecrate::tree_kem::node::Parent; usecrate::tree_kem::TreeKemPublic; use alloc::collections::VecDeque; use alloc::vec; use alloc::vec::Vec; use core::fmt::{self, Debug}; use itertools::Itertools; use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize}; use mls_rs_core::error::IntoAnyError; use tree_math::TreeIndex;
// Update hashes after `committer` makes changes to the tree. `path_blank` is the // list of leaves whose paths were blanked, i.e. updates and removes. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn update_hashes<P: CipherSuiteProvider>(
&mutself,
updated_leaves: &[LeafIndex],
cipher_suite_provider: &P,
) -> Result<(), MlsError> { let num_leaves = self.total_leaf_count();
let trailing_blanks = (0..num_leaves)
.rev()
.map_while(|l| { self.tree_hashes
.current
.get(2 * l as usize)
.is_none()
.then_some(LeafIndex(l))
})
.collect::<Vec<_>>();
// Update the current hashes for direct paths of all modified leaves.
tree_hash(
&mutself.tree_hashes.current,
&self.nodes,
Some([updated_leaves, &trailing_blanks].concat()),
&[],
num_leaves,
cipher_suite_provider,
)
.await?;
Ok(())
}
// Initialize all hashes after creating / importing a tree. #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] asyncfn initialize_hashes<P>(&mutself, cipher_suite_provider: &P) -> Result<(), MlsError> where
P: CipherSuiteProvider,
{ ifself.tree_hashes.current.is_empty() { let num_leaves = self.total_leaf_count();
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pub(crate) asyncfn compute_original_hashes<P: CipherSuiteProvider>(
&self,
cipher_suite: &P,
) -> Result<Vec<TreeHash>, MlsError> { let num_leaves = self.nodes.total_leaf_count() as usize; let root = (num_leaves as u32).root();
// The value `filtered_sets[n]` is a list of all ancestors `a` of `n` s.t. we have to compute // the tree hash of `n` with the unmerged leaves of `a` filtered out. letmut filtered_sets = vec![vec![]; num_leaves * 2 - 1];
filtered_sets[root as usize].push(root); letmut tree_hashes = vec![vec![]; num_leaves * 2 - 1];
let bfs_iter = BfsIterTopDown::new(num_leaves).skip(1);
for n in bfs_iter { let Some(ps) = (n as u32).parent_sibling(&(num_leaves as u32)) else { break;
};
let p = ps.parent;
// Clippy's suggestion `filtered_sets[n].clone_from(&filtered_sets[p as usize])` is wrong and does not compile #[allow(clippy::assigning_clones)]
{
filtered_sets[n] = filtered_sets[p as usize].clone();
}
ifself.different_unmerged(*filtered_sets[p as usize].last().unwrap(), p)? {
filtered_sets[n].push(p);
// Compute tree hash of `n` without unmerged leaves of `p`. This also computes the tree hash // for any descendants of `n` added to `filtered_sets` later via `clone`. let (start_leaf, end_leaf) = tree_math::subtree(n as u32);
tree_hash(
&mut tree_hashes[p as usize],
&self.nodes,
Some((*start_leaf..*end_leaf).map(LeafIndex).collect_vec()),
&self.nodes.borrow_as_parent(p)?.unmerged_leaves,
num_leaves as u32,
cipher_suite,
)
.await?;
}
}
// Set the `original_hashes` based on the computed `hashes`. letmut original_hashes = vec![TreeHash::default(); num_leaves * 2 - 1];
// If root has unmerged leaves, we recompute it's original hash. Else, we can use the current hash. let root_original = if !self.nodes.is_blank(root)? && !self.nodes.is_leaf(root) { let root_unmerged = &self.nodes.borrow_as_parent(root)?.unmerged_leaves;
if !root_unmerged.is_empty() { letmut hashes = vec![];
for l in leaves_to_update.iter().filter(|l| ***l < num_leaves) { let leaf = (!filtered_leaves.contains(l))
.then_some(nodes.borrow_as_leaf(*l).ok())
.flatten();
hashes[2 * **l as usize] = TreeHash(hash_for_leaf(*l, leaf, cipher_suite_provider).await?);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.