mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 19:02:42 +00:00
Squashed commit of the following: commit1ba4f80cc0Author: Michael Sproul <michael@sigmaprime.io> Date: Tue Jan 17 11:43:18 2023 +1100 Bye 1.0.0 beta, hello 0.5.x commita862b234b2Author: Michael Sproul <michael@sigmaprime.io> Date: Tue Jan 17 10:54:46 2023 +1100 Cargo fmt commite29f358a9eAuthor: Michael Sproul <michael@sigmaprime.io> Date: Mon Jan 16 18:21:42 2023 +1100 It compiles :O commit1ee4514b7dAuthor: Michael Sproul <michael@sigmaprime.io> Date: Mon Jan 16 17:27:10 2023 +1100 Ethereum hashing commit69bdd1d61fAuthor: Michael Sproul <michael@sigmaprime.io> Date: Mon Jan 16 17:24:58 2023 +1100 Tree hash et al commit7cae5d99d7Author: Michael Sproul <michael@sigmaprime.io> Date: Mon Jan 16 17:21:03 2023 +1100 Delete crates! commitdd9ee38084Author: Michael Sproul <michael@sigmaprime.io> Date: Mon Jan 16 17:19:19 2023 +1100 Delete overrides commit0d54534eb4Author: Michael Sproul <michael@sigmaprime.io> Date: Mon Jan 16 17:19:04 2023 +1100 Crate renames
103 lines
3.8 KiB
Rust
103 lines
3.8 KiB
Rust
use ethereum_hashing::hash;
|
|
use int_to_bytes::int_to_bytes32;
|
|
use merkle_proof::{MerkleTree, MerkleTreeError};
|
|
use safe_arith::SafeArith;
|
|
use types::{DepositTreeSnapshot, FinalizedExecutionBlock, Hash256};
|
|
|
|
/// Emulates the eth1 deposit contract merkle tree.
|
|
#[derive(PartialEq)]
|
|
pub struct DepositDataTree {
|
|
tree: MerkleTree,
|
|
mix_in_length: usize,
|
|
finalized_execution_block: Option<FinalizedExecutionBlock>,
|
|
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,
|
|
finalized_execution_block: None,
|
|
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) -> Result<(Hash256, Vec<Hash256>), MerkleTreeError> {
|
|
let (root, mut proof) = self.tree.generate_proof(index, self.depth)?;
|
|
proof.push(Hash256::from_slice(&self.length_bytes()));
|
|
Ok((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(())
|
|
}
|
|
|
|
/// Finalize deposits up to `finalized_execution_block.deposit_count`
|
|
pub fn finalize(
|
|
&mut self,
|
|
finalized_execution_block: FinalizedExecutionBlock,
|
|
) -> Result<(), MerkleTreeError> {
|
|
self.tree
|
|
.finalize_deposits(finalized_execution_block.deposit_count as usize, self.depth)?;
|
|
self.finalized_execution_block = Some(finalized_execution_block);
|
|
Ok(())
|
|
}
|
|
|
|
/// Get snapshot of finalized deposit tree (if tree is finalized)
|
|
pub fn get_snapshot(&self) -> Option<DepositTreeSnapshot> {
|
|
let finalized_execution_block = self.finalized_execution_block.as_ref()?;
|
|
Some(DepositTreeSnapshot {
|
|
finalized: self.tree.get_finalized_hashes(),
|
|
deposit_root: finalized_execution_block.deposit_root,
|
|
deposit_count: finalized_execution_block.deposit_count,
|
|
execution_block_hash: finalized_execution_block.block_hash,
|
|
execution_block_height: finalized_execution_block.block_height,
|
|
})
|
|
}
|
|
|
|
/// Create a new Merkle tree from a snapshot
|
|
pub fn from_snapshot(
|
|
snapshot: &DepositTreeSnapshot,
|
|
depth: usize,
|
|
) -> Result<Self, MerkleTreeError> {
|
|
Ok(Self {
|
|
tree: MerkleTree::from_finalized_snapshot(
|
|
&snapshot.finalized,
|
|
snapshot.deposit_count as usize,
|
|
depth,
|
|
)?,
|
|
mix_in_length: snapshot.deposit_count as usize,
|
|
finalized_execution_block: Some(snapshot.into()),
|
|
depth,
|
|
})
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn print_tree(&self) {
|
|
self.tree.print_node(0);
|
|
println!("========================================================");
|
|
}
|
|
}
|