-
Notifications
You must be signed in to change notification settings - Fork 738
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 18 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 |
---|---|---|
|
@@ -3,6 +3,8 @@ use eth2_hashing::hash; | |
use tree_hash::TreeHash; | ||
use types::{Deposit, Hash256}; | ||
|
||
const DEPOSIT_CONTRACT_TREE_DEPTH: usize = 32; | ||
|
||
#[derive(Debug, PartialEq, Clone)] | ||
pub enum Error { | ||
/// A deposit log was added when a prior deposit was not already in the cache. | ||
|
@@ -71,13 +73,34 @@ impl DepositDataTree { | |
/// 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>, | ||
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. @paulhauner Perhaps this should be named 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. Agreed |
||
deposit_contract_deploy_block: u64, | ||
} | ||
|
||
impl Default for DepositCache { | ||
fn default() -> Self { | ||
DepositCache { | ||
logs: Vec::new(), | ||
roots: Vec::new(), | ||
// 0 to be compatible with Service::Config. Should be ideally 1 | ||
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. Perhaps we change |
||
deposit_contract_deploy_block: 0, | ||
} | ||
} | ||
} | ||
|
||
impl DepositCache { | ||
/// Create new `DepositCache` given block number at which deposit | ||
/// contract was deployed. | ||
pub fn new(deposit_contract_deploy_block: u64) -> Self { | ||
DepositCache { | ||
logs: Vec::new(), | ||
roots: Vec::new(), | ||
deposit_contract_deploy_block, | ||
} | ||
} | ||
|
||
/// Returns the number of deposits available in the cache. | ||
pub fn len(&self) -> usize { | ||
self.logs.len() | ||
|
@@ -203,6 +226,55 @@ 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 `DepositLog` that was emitted at or just before `block_number` | ||
/// and returns the deposit root at that state. | ||
/// | ||
/// Note: This method can be potentially optimized by not recreating the `DepositDataTree` | ||
/// at every invocation and caching the tree upto the last added deposit. | ||
pub fn get_deposit_root_from_cache(&self, block_number: u64) -> Option<Hash256> { | ||
let index = self.get_deposit_count_from_cache(block_number)?; | ||
let roots = self.roots.get(0..index as usize)?; | ||
let tree = DepositDataTree::create(roots, index as usize, DEPOSIT_CONTRACT_TREE_DEPTH); | ||
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. As you mentioned, this is going to be fairly inefficient. For our testnet, this means that if we sync a cache of I think a fairly easy solution to this would be to attach a Thoughts? 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, this sounds perfect 👍 |
||
Some(tree.root()) | ||
} | ||
} | ||
|
||
/// 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.
This const tends to keep getting duplicated around, perhaps we can import this instead:
lighthouse/eth2/types/src/deposit.rs
Line 10 in 24e941d