3412a3ec54
## Issue Addressed Resolves #1100 ## Proposed Changes * Implement the `SafeArith` trait for `Slot` and `Epoch`, so that methods like `safe_add` become available. * Tweak the `SafeArith` trait to allow a different `Rhs` type (analagous to `std::ops::Add`, etc). * Add a `legacy-arith` feature to `types` and `state_processing` that conditionally enables implementations of the `std` ops with saturating semantics. * Check compilation of `types` and `state_processing` _without_ `legacy-arith` on CI, thus guaranteeing that they only use the `SafeArith` primitives 🎉 ## Additional Info The `legacy-arith` feature gets turned on by all higher-level crates that depend on `state_processing` or `types`, thus allowing the beacon chain, networking, and other components to continue to rely on the availability of ops like `+`, `-`, `*`, etc. **This is a consensus-breaking change**, but brings us in line with the spec, and our incompatibilities shouldn't have been reachable with any valid configuration of Eth2 parameters.
54 lines
1.8 KiB
Rust
54 lines
1.8 KiB
Rust
use eth2_hashing::hash;
|
|
use int_to_bytes::int_to_bytes32;
|
|
use merkle_proof::{MerkleTree, MerkleTreeError};
|
|
use safe_arith::SafeArith;
|
|
use types::Hash256;
|
|
|
|
/// Emulates the eth1 deposit contract merkle tree.
|
|
pub struct DepositDataTree {
|
|
tree: MerkleTree,
|
|
mix_in_length: usize,
|
|
depth: usize,
|
|
}
|
|
|
|
impl DepositDataTree {
|
|
/// Create a new Merkle tree from a list of leaves (`DepositData::tree_hash_root`) and a fixed depth.
|
|
pub fn create(leaves: &[Hash256], mix_in_length: usize, depth: usize) -> Self {
|
|
Self {
|
|
tree: MerkleTree::create(leaves, depth),
|
|
mix_in_length,
|
|
depth,
|
|
}
|
|
}
|
|
|
|
/// Returns 32 bytes representing the "mix in length" for the merkle root of this tree.
|
|
fn length_bytes(&self) -> Vec<u8> {
|
|
int_to_bytes32(self.mix_in_length as u64)
|
|
}
|
|
|
|
/// Retrieve the root hash of this Merkle tree with the length mixed in.
|
|
pub fn root(&self) -> Hash256 {
|
|
let mut preimage = [0; 64];
|
|
preimage[0..32].copy_from_slice(&self.tree.hash()[..]);
|
|
preimage[32..64].copy_from_slice(&self.length_bytes());
|
|
Hash256::from_slice(&hash(&preimage))
|
|
}
|
|
|
|
/// Return the leaf at `index` and a Merkle proof of its inclusion.
|
|
///
|
|
/// The Merkle proof is in "bottom-up" order, starting with a leaf node
|
|
/// and moving up the tree. Its length will be exactly equal to `depth + 1`.
|
|
pub fn generate_proof(&self, index: usize) -> (Hash256, Vec<Hash256>) {
|
|
let (root, mut proof) = self.tree.generate_proof(index, self.depth);
|
|
proof.push(Hash256::from_slice(&self.length_bytes()));
|
|
(root, proof)
|
|
}
|
|
|
|
/// Add a deposit to the merkle tree.
|
|
pub fn push_leaf(&mut self, leaf: Hash256) -> Result<(), MerkleTreeError> {
|
|
self.tree.push_leaf(leaf, self.depth)?;
|
|
self.mix_in_length.safe_add_assign(1)?;
|
|
Ok(())
|
|
}
|
|
}
|