-
Notifications
You must be signed in to change notification settings - Fork 759
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make eth1 caching work with fast synced node #709
Changes from 24 commits
f82e275
e331816
9fbc01c
365d6a2
e3d0325
a8e99da
bba7a5d
3f4f88c
1ec606c
9f14df3
69f49de
8d0b5db
ffda83f
921dd4a
cc246aa
754eaa2
7706f8f
e709f7e
6378db8
63c8616
0777c04
39a4871
040a57d
35ac316
5beb4c8
7132c3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
use crate::DepositLog; | ||
use eth2_hashing::hash; | ||
use tree_hash::TreeHash; | ||
use types::{Deposit, Hash256}; | ||
use types::{Deposit, Hash256, DEPOSIT_TREE_DEPTH}; | ||
|
||
#[derive(Debug, PartialEq, Clone)] | ||
#[derive(Debug, PartialEq)] | ||
pub enum Error { | ||
/// A deposit log was added when a prior deposit was not already in the cache. | ||
/// | ||
|
@@ -23,6 +23,8 @@ pub enum Error { | |
/// | ||
/// E.g., you cannot request deposit 10 when the deposit count is 9. | ||
DepositCountInvalid { deposit_count: u64, range_end: u64 }, | ||
/// Error with the merkle tree for deposits. | ||
DepositTreeError(merkle_proof::MerkleTreeError), | ||
/// An unexpected condition was encountered. | ||
InternalError(String), | ||
} | ||
|
@@ -66,18 +68,56 @@ impl DepositDataTree { | |
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<(), Error> { | ||
self.tree | ||
.push_leaf(leaf, self.depth) | ||
.map_err(Error::DepositTreeError)?; | ||
self.mix_in_length += 1; | ||
Ok(()) | ||
} | ||
} | ||
|
||
/// Mirrors the merkle tree of deposits in the eth1 deposit contract. | ||
/// | ||
/// Provides `Deposit` objects with merkle proofs included. | ||
#[derive(Default)] | ||
pub struct DepositCache { | ||
logs: Vec<DepositLog>, | ||
roots: Vec<Hash256>, | ||
deposit_contract_deploy_block: u64, | ||
/// An incremental merkle tree which represents the current state of the | ||
/// deposit contract tree. | ||
deposit_tree: DepositDataTree, | ||
/// Vector of deposit roots. `deposit_roots[i]` denotes `deposit_root` at | ||
/// `deposit_index` `i`. | ||
deposit_roots: Vec<Hash256>, | ||
} | ||
|
||
impl Default for DepositCache { | ||
fn default() -> Self { | ||
let deposit_tree = DepositDataTree::create(&[], 0, DEPOSIT_TREE_DEPTH); | ||
let deposit_roots = vec![deposit_tree.root()]; | ||
DepositCache { | ||
logs: Vec::new(), | ||
roots: Vec::new(), | ||
deposit_contract_deploy_block: 1, | ||
deposit_tree, | ||
deposit_roots, | ||
} | ||
} | ||
} | ||
|
||
impl DepositCache { | ||
/// Create new `DepositCache` given block number at which deposit | ||
/// contract was deployed. | ||
pub fn new(deposit_contract_deploy_block: u64) -> Self { | ||
DepositCache { | ||
deposit_contract_deploy_block, | ||
..Self::default() | ||
} | ||
} | ||
|
||
/// Returns the number of deposits available in the cache. | ||
pub fn len(&self) -> usize { | ||
self.logs.len() | ||
|
@@ -114,10 +154,11 @@ impl DepositCache { | |
/// - If a log with `log.index` is already known, but the given `log` is distinct to it. | ||
pub fn insert_log(&mut self, log: DepositLog) -> Result<(), Error> { | ||
if log.index == self.logs.len() as u64 { | ||
self.roots | ||
.push(Hash256::from_slice(&log.deposit_data.tree_hash_root())); | ||
let deposit = Hash256::from_slice(&log.deposit_data.tree_hash_root()); | ||
self.roots.push(deposit); | ||
self.logs.push(log); | ||
|
||
self.deposit_tree.push_leaf(deposit)?; | ||
self.deposit_roots.push(self.deposit_tree.root()); | ||
Ok(()) | ||
} else if log.index < self.logs.len() as u64 { | ||
if self.logs[log.index as usize] == log { | ||
|
@@ -203,6 +244,50 @@ impl DepositCache { | |
Ok((tree.root(), deposits)) | ||
} | ||
} | ||
|
||
/// Gets the deposit count at block height = block_number. | ||
/// | ||
/// Fetches the `DepositLog` that was emitted at or just before `block_number` | ||
/// and returns the deposit count as `index + 1`. | ||
/// | ||
/// Returns `None` if block number queried is 0 or less than deposit_contract_deployed block. | ||
pub fn get_deposit_count_from_cache(&self, block_number: u64) -> Option<u64> { | ||
// Contract cannot be deployed in 0'th block | ||
if block_number == 0 { | ||
return None; | ||
} | ||
if block_number < self.deposit_contract_deploy_block { | ||
return None; | ||
} | ||
// Return 0 if block_num queried is before first deposit | ||
if let Some(first_deposit) = self.logs.first() { | ||
if first_deposit.block_number > block_number { | ||
return Some(0); | ||
} | ||
} | ||
let index = self | ||
.logs | ||
.binary_search_by(|deposit| deposit.block_number.cmp(&block_number)); | ||
match index { | ||
Ok(index) => return self.logs.get(index).map(|x| x.index + 1), | ||
Err(prev) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup you are right |
||
return Some( | ||
self.logs | ||
.get(prev.saturating_sub(1)) | ||
.map_or(0, |x| x.index + 1), | ||
) | ||
} | ||
} | ||
} | ||
|
||
/// Gets the deposit root at block height = block_number. | ||
/// | ||
/// Fetches the `deposit_count` on or just before the queried `block_number` | ||
/// and queries the `deposit_roots` map to get the corresponding `deposit_root`. | ||
pub fn get_deposit_root_from_cache(&self, block_number: u64) -> Option<Hash256> { | ||
let index = self.get_deposit_count_from_cache(block_number)?; | ||
Some(self.deposit_roots.get(index as usize)?.clone()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like how you indexed by deposit count, this is better than my suggestion. |
||
} | ||
} | ||
|
||
/// Returns `int` as little-endian bytes with a length of 32. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paulhauner Perhaps this should be named
leafs
instead ofroots
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed