mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-09 03:17:55 +00:00
Altair consensus changes and refactors (#2279)
## Proposed Changes Implement the consensus changes necessary for the upcoming Altair hard fork. ## Additional Info This is quite a heavy refactor, with pivotal types like the `BeaconState` and `BeaconBlock` changing from structs to enums. This ripples through the whole codebase with field accesses changing to methods, e.g. `state.slot` => `state.slot()`. Co-authored-by: realbigsean <seananderson33@gmail.com>
This commit is contained in:
@@ -2,6 +2,7 @@ use crate::metrics;
|
||||
use eth1::{Config as Eth1Config, Eth1Block, Service as HttpService};
|
||||
use eth2::lighthouse::Eth1SyncStatusData;
|
||||
use eth2_hashing::hash;
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use slog::{debug, error, trace, Logger};
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -364,7 +365,7 @@ impl<T: EthSpec> Eth1ChainBackend<T> for DummyEth1ChainBackend<T> {
|
||||
|
||||
Ok(Eth1Data {
|
||||
deposit_root: Hash256::from_slice(&deposit_root),
|
||||
deposit_count: state.eth1_deposit_index,
|
||||
deposit_count: state.eth1_deposit_index(),
|
||||
block_hash: Hash256::from_slice(&block_hash),
|
||||
})
|
||||
}
|
||||
@@ -451,9 +452,9 @@ impl<T: EthSpec> CachingEth1Backend<T> {
|
||||
impl<T: EthSpec> Eth1ChainBackend<T> for CachingEth1Backend<T> {
|
||||
fn eth1_data(&self, state: &BeaconState<T>, spec: &ChainSpec) -> Result<Eth1Data, Error> {
|
||||
let period = T::SlotsPerEth1VotingPeriod::to_u64();
|
||||
let voting_period_start_slot = (state.slot / period) * period;
|
||||
let voting_period_start_slot = (state.slot() / period) * period;
|
||||
let voting_period_start_seconds = slot_start_seconds::<T>(
|
||||
state.genesis_time,
|
||||
state.genesis_time(),
|
||||
spec.seconds_per_slot,
|
||||
voting_period_start_slot,
|
||||
);
|
||||
@@ -491,13 +492,13 @@ impl<T: EthSpec> Eth1ChainBackend<T> for CachingEth1Backend<T> {
|
||||
vote
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let vote = state.eth1_data.clone();
|
||||
let vote = state.eth1_data().clone();
|
||||
error!(
|
||||
self.log,
|
||||
"No valid eth1_data votes, `votes_to_consider` empty";
|
||||
"lowest_block_number" => self.core.lowest_block_number(),
|
||||
"earliest_block_timestamp" => self.core.earliest_block_timestamp(),
|
||||
"genesis_time" => state.genesis_time,
|
||||
"genesis_time" => state.genesis_time(),
|
||||
"outcome" => "casting `state.eth1_data` as eth1 vote"
|
||||
);
|
||||
metrics::inc_counter(&metrics::DEFAULT_ETH1_VOTES);
|
||||
@@ -522,11 +523,11 @@ impl<T: EthSpec> Eth1ChainBackend<T> for CachingEth1Backend<T> {
|
||||
eth1_data_vote: &Eth1Data,
|
||||
_spec: &ChainSpec,
|
||||
) -> Result<Vec<Deposit>, Error> {
|
||||
let deposit_index = state.eth1_deposit_index;
|
||||
let deposit_index = state.eth1_deposit_index();
|
||||
let deposit_count = if let Some(new_eth1_data) = get_new_eth1_data(state, eth1_data_vote)? {
|
||||
new_eth1_data.deposit_count
|
||||
} else {
|
||||
state.eth1_data.deposit_count
|
||||
state.eth1_data().deposit_count
|
||||
};
|
||||
|
||||
match deposit_index.cmp(&deposit_count) {
|
||||
@@ -609,7 +610,7 @@ fn collect_valid_votes<T: EthSpec>(
|
||||
) -> Eth1DataVoteCount {
|
||||
let mut valid_votes = HashMap::new();
|
||||
state
|
||||
.eth1_data_votes
|
||||
.eth1_data_votes()
|
||||
.iter()
|
||||
.filter_map(|vote| {
|
||||
votes_to_consider
|
||||
@@ -633,13 +634,6 @@ fn find_winning_vote(valid_votes: Eth1DataVoteCount) -> Option<Eth1Data> {
|
||||
.map(|((eth1_data, _), _)| eth1_data.clone())
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 32.
|
||||
fn int_to_bytes32(int: u64) -> Vec<u8> {
|
||||
let mut vec = int.to_le_bytes().to_vec();
|
||||
vec.resize(32, 0);
|
||||
vec
|
||||
}
|
||||
|
||||
/// Returns the unix-epoch seconds at the start of the given `slot`.
|
||||
fn slot_start_seconds<T: EthSpec>(
|
||||
genesis_unix_seconds: u64,
|
||||
@@ -666,7 +660,7 @@ fn is_candidate_block(block: &Eth1Block, period_start: u64, spec: &ChainSpec) ->
|
||||
mod test {
|
||||
use super::*;
|
||||
use environment::null_logger;
|
||||
use types::{test_utils::DepositTestTask, MinimalEthSpec};
|
||||
use types::{DepositData, MinimalEthSpec, Signature};
|
||||
|
||||
type E = MinimalEthSpec;
|
||||
|
||||
@@ -680,9 +674,9 @@ mod test {
|
||||
|
||||
fn get_voting_period_start_seconds(state: &BeaconState<E>, spec: &ChainSpec) -> u64 {
|
||||
let period = <E as EthSpec>::SlotsPerEth1VotingPeriod::to_u64();
|
||||
let voting_period_start_slot = (state.slot / period) * period;
|
||||
let voting_period_start_slot = (state.slot() / period) * period;
|
||||
slot_start_seconds::<E>(
|
||||
state.genesis_time,
|
||||
state.genesis_time(),
|
||||
spec.seconds_per_slot,
|
||||
voting_period_start_slot,
|
||||
)
|
||||
@@ -723,10 +717,7 @@ mod test {
|
||||
mod eth1_chain_json_backend {
|
||||
use super::*;
|
||||
use eth1::DepositLog;
|
||||
use types::{
|
||||
test_utils::{generate_deterministic_keypair, TestingDepositBuilder},
|
||||
EthSpec, MainnetEthSpec,
|
||||
};
|
||||
use types::{test_utils::generate_deterministic_keypair, EthSpec, MainnetEthSpec};
|
||||
|
||||
fn get_eth1_chain() -> Eth1Chain<CachingEth1Backend<E>, E> {
|
||||
let eth1_config = Eth1Config {
|
||||
@@ -743,13 +734,17 @@ mod test {
|
||||
|
||||
fn get_deposit_log(i: u64, spec: &ChainSpec) -> DepositLog {
|
||||
let keypair = generate_deterministic_keypair(i as usize);
|
||||
let mut builder =
|
||||
TestingDepositBuilder::new(keypair.pk.clone(), spec.max_effective_balance);
|
||||
builder.sign(DepositTestTask::Valid, &keypair, spec);
|
||||
let deposit_data = builder.build().data;
|
||||
let mut deposit = DepositData {
|
||||
pubkey: keypair.pk.into(),
|
||||
withdrawal_credentials: Hash256::zero(),
|
||||
amount: spec.max_effective_balance,
|
||||
signature: Signature::empty().into(),
|
||||
};
|
||||
|
||||
deposit.signature = deposit.create_signature(&keypair.sk, &E::default_spec());
|
||||
|
||||
DepositLog {
|
||||
deposit_data,
|
||||
deposit_data: deposit,
|
||||
block_number: i,
|
||||
index: i,
|
||||
signature_is_valid: true,
|
||||
@@ -768,8 +763,8 @@ mod test {
|
||||
);
|
||||
|
||||
let mut state: BeaconState<E> = BeaconState::new(0, get_eth1_data(0), &spec);
|
||||
state.eth1_deposit_index = 0;
|
||||
state.eth1_data.deposit_count = 0;
|
||||
*state.eth1_deposit_index_mut() = 0;
|
||||
state.eth1_data_mut().deposit_count = 0;
|
||||
|
||||
assert!(
|
||||
eth1_chain
|
||||
@@ -778,7 +773,7 @@ mod test {
|
||||
"should succeed if cache is empty but no deposits are required"
|
||||
);
|
||||
|
||||
state.eth1_data.deposit_count = 1;
|
||||
state.eth1_data_mut().deposit_count = 1;
|
||||
|
||||
assert!(
|
||||
eth1_chain
|
||||
@@ -821,8 +816,8 @@ mod test {
|
||||
);
|
||||
|
||||
let mut state: BeaconState<E> = BeaconState::new(0, get_eth1_data(0), &spec);
|
||||
state.eth1_deposit_index = 0;
|
||||
state.eth1_data.deposit_count = 0;
|
||||
*state.eth1_deposit_index_mut() = 0;
|
||||
state.eth1_data_mut().deposit_count = 0;
|
||||
|
||||
assert!(
|
||||
eth1_chain
|
||||
@@ -832,10 +827,10 @@ mod test {
|
||||
);
|
||||
|
||||
(0..3).for_each(|initial_deposit_index| {
|
||||
state.eth1_deposit_index = initial_deposit_index as u64;
|
||||
*state.eth1_deposit_index_mut() = initial_deposit_index as u64;
|
||||
|
||||
(initial_deposit_index..deposits.len()).for_each(|i| {
|
||||
state.eth1_data.deposit_count = i as u64;
|
||||
state.eth1_data_mut().deposit_count = i as u64;
|
||||
|
||||
let deposits_for_inclusion = eth1_chain
|
||||
.deposits_for_block_inclusion(&state, &Eth1Data::default(), spec)
|
||||
@@ -888,7 +883,8 @@ mod test {
|
||||
.eth1_data_for_block_production(&state, &spec)
|
||||
.expect("should produce default eth1 data vote");
|
||||
assert_eq!(
|
||||
a, state.eth1_data,
|
||||
a,
|
||||
*state.eth1_data(),
|
||||
"default vote should be same as state.eth1_data"
|
||||
);
|
||||
}
|
||||
@@ -908,7 +904,7 @@ mod test {
|
||||
|
||||
let mut state: BeaconState<E> = BeaconState::new(0, get_eth1_data(0), &spec);
|
||||
|
||||
state.slot = Slot::from(slots_per_eth1_voting_period * 10);
|
||||
*state.slot_mut() = Slot::from(slots_per_eth1_voting_period * 10);
|
||||
let follow_distance_seconds = eth1_follow_distance * spec.seconds_per_eth1_block;
|
||||
let voting_period_start = get_voting_period_start_seconds(&state, &spec);
|
||||
let start_eth1_block = voting_period_start - follow_distance_seconds * 2;
|
||||
@@ -974,8 +970,8 @@ mod test {
|
||||
let eth1_follow_distance = spec.eth1_follow_distance;
|
||||
|
||||
let mut state: BeaconState<E> = BeaconState::new(0, get_eth1_data(0), &spec);
|
||||
state.genesis_time = 0;
|
||||
state.slot = Slot::from(slots_per_eth1_voting_period * 10);
|
||||
*state.genesis_time_mut() = 0;
|
||||
*state.slot_mut() = Slot::from(slots_per_eth1_voting_period * 10);
|
||||
|
||||
let follow_distance_seconds = eth1_follow_distance * spec.seconds_per_eth1_block;
|
||||
let voting_period_start = get_voting_period_start_seconds(&state, &spec);
|
||||
@@ -1055,7 +1051,7 @@ mod test {
|
||||
|
||||
let votes_to_consider = get_eth1_data_vec(slots, 0);
|
||||
|
||||
state.eth1_data_votes = votes_to_consider[0..slots as usize / 4]
|
||||
*state.eth1_data_votes_mut() = votes_to_consider[0..slots as usize / 4]
|
||||
.iter()
|
||||
.map(|(eth1_data, _)| eth1_data)
|
||||
.cloned()
|
||||
@@ -1084,7 +1080,7 @@ mod test {
|
||||
.expect("should have some eth1 data")
|
||||
.clone();
|
||||
|
||||
state.eth1_data_votes = vec![duplicate_eth1_data.clone(); 4]
|
||||
*state.eth1_data_votes_mut() = vec![duplicate_eth1_data.clone(); 4]
|
||||
.iter()
|
||||
.map(|(eth1_data, _)| eth1_data)
|
||||
.cloned()
|
||||
|
||||
Reference in New Issue
Block a user