2020-02-04 01:43:04 +00:00
|
|
|
use eth2_hashing::hash;
|
|
|
|
use int_to_bytes::int_to_bytes32;
|
|
|
|
use merkle_proof::{MerkleTree, MerkleTreeError};
|
2020-04-20 02:35:11 +00:00
|
|
|
use safe_arith::SafeArith;
|
2020-02-04 01:43:04 +00:00
|
|
|
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)?;
|
Remove saturating arith from state_processing (#1644)
## 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 :tada:
## 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.
2020-09-25 05:18:21 +00:00
|
|
|
self.mix_in_length.safe_add_assign(1)?;
|
2020-02-04 01:43:04 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|