Merge remote-tracking branch 'origin/master' into spec-v0.12

This commit is contained in:
Michael Sproul
2020-06-17 12:34:11 +10:00
60 changed files with 877 additions and 1242 deletions

View File

@@ -17,19 +17,21 @@ mod tests {
use sloggers::{null::NullLoggerBuilder, Build};
use slot_clock::{SlotClock, SystemTimeSlotClock};
use std::time::{Duration, SystemTime};
use store::MemoryStore;
use store::config::StoreConfig;
use store::{HotColdDB, MemoryStore};
use tempfile::tempdir;
use types::{CommitteeIndex, EnrForkId, EthSpec, MinimalEthSpec};
const SLOT_DURATION_MILLIS: u64 = 200;
type TestBeaconChainType = Witness<
MemoryStore<MinimalEthSpec>,
NullMigrator,
SystemTimeSlotClock,
CachingEth1Backend<MinimalEthSpec, MemoryStore<MinimalEthSpec>>,
CachingEth1Backend<MinimalEthSpec>,
MinimalEthSpec,
NullEventHandler<MinimalEthSpec>,
MemoryStore<MinimalEthSpec>,
MemoryStore<MinimalEthSpec>,
>;
pub struct TestBeaconChain {
@@ -44,11 +46,14 @@ mod tests {
let keypairs = generate_deterministic_keypairs(1);
let log = get_logger();
let store =
HotColdDB::open_ephemeral(StoreConfig::default(), spec.clone(), log.clone())
.unwrap();
let chain = Arc::new(
BeaconChainBuilder::new(MinimalEthSpec)
.logger(log.clone())
.custom_spec(spec.clone())
.store(Arc::new(MemoryStore::open()))
.store(Arc::new(store))
.store_migrator(NullMigrator)
.data_dir(data_dir.path().to_path_buf())
.genesis_state(
@@ -83,7 +88,7 @@ mod tests {
}
lazy_static! {
static ref CHAIN: TestBeaconChain = { TestBeaconChain::new_with_system_clock() };
static ref CHAIN: TestBeaconChain = TestBeaconChain::new_with_system_clock();
}
fn get_attestation_service() -> AttestationService<TestBeaconChainType> {

View File

@@ -1,13 +1,15 @@
use eth2_libp2p::Enr;
use rlp;
use std::sync::Arc;
use store::{DBColumn, Error as StoreError, Store, StoreItem};
use store::{DBColumn, Error as StoreError, HotColdDB, ItemStore, StoreItem};
use types::{EthSpec, Hash256};
/// 32-byte key for accessing the `DhtEnrs`.
pub const DHT_DB_KEY: &str = "PERSISTEDDHTPERSISTEDDHTPERSISTE";
pub fn load_dht<T: Store<E>, E: EthSpec>(store: Arc<T>) -> Vec<Enr> {
pub fn load_dht<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
store: Arc<HotColdDB<E, Hot, Cold>>,
) -> Vec<Enr> {
// Load DHT from store
let key = Hash256::from_slice(&DHT_DB_KEY.as_bytes());
match store.get_item(&key) {
@@ -20,8 +22,8 @@ pub fn load_dht<T: Store<E>, E: EthSpec>(store: Arc<T>) -> Vec<Enr> {
}
/// Attempt to persist the ENR's in the DHT to `self.store`.
pub fn persist_dht<T: Store<E>, E: EthSpec>(
store: Arc<T>,
pub fn persist_dht<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
store: Arc<HotColdDB<E, Hot, Cold>>,
enrs: Vec<Enr>,
) -> Result<(), store::Error> {
let key = Hash256::from_slice(&DHT_DB_KEY.as_bytes());
@@ -56,14 +58,19 @@ impl StoreItem for PersistedDht {
mod tests {
use super::*;
use eth2_libp2p::Enr;
use sloggers::{null::NullLoggerBuilder, Build};
use std::str::FromStr;
use std::sync::Arc;
use store::{MemoryStore, Store};
use types::Hash256;
use types::MinimalEthSpec;
use store::config::StoreConfig;
use store::{HotColdDB, MemoryStore};
use types::{ChainSpec, Hash256, MinimalEthSpec};
#[test]
fn test_persisted_dht() {
let store = Arc::new(MemoryStore::<MinimalEthSpec>::open());
let log = NullLoggerBuilder.build().unwrap();
let store: HotColdDB<
MinimalEthSpec,
MemoryStore<MinimalEthSpec>,
MemoryStore<MinimalEthSpec>,
> = HotColdDB::open_ephemeral(StoreConfig::default(), ChainSpec::minimal(), log).unwrap();
let enrs = vec![Enr::from_str("enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8").unwrap()];
let key = Hash256::from_slice(&DHT_DB_KEY.as_bytes());
store

View File

@@ -10,10 +10,10 @@ use beacon_chain::{
};
use eth2_libp2p::rpc::*;
use eth2_libp2p::{NetworkGlobals, PeerId, Request, Response};
use itertools::process_results;
use slog::{debug, error, o, trace, warn};
use ssz::Encode;
use std::sync::Arc;
use store::Store;
use tokio::sync::mpsc;
use types::{
Attestation, ChainSpec, Epoch, EthSpec, Hash256, SignedAggregateAndProof, SignedBeaconBlock,
@@ -362,20 +362,29 @@ impl<T: BeaconChainTypes> Processor<T> {
// pick out the required blocks, ignoring skip-slots and stepping by the step parameter;
let mut last_block_root = None;
let block_roots = forwards_block_root_iter
.take_while(|(_root, slot)| slot.as_u64() < req.start_slot + req.count * req.step)
// map skip slots to None
.map(|(root, _slot)| {
let result = if Some(root) == last_block_root {
None
} else {
Some(root)
};
last_block_root = Some(root);
result
})
.step_by(req.step as usize)
.collect::<Vec<_>>();
let maybe_block_roots = process_results(forwards_block_root_iter, |iter| {
iter.take_while(|(_, slot)| slot.as_u64() < req.start_slot + req.count * req.step)
// map skip slots to None
.map(|(root, _)| {
let result = if Some(root) == last_block_root {
None
} else {
Some(root)
};
last_block_root = Some(root);
result
})
.step_by(req.step as usize)
.collect::<Vec<Option<Hash256>>>()
});
let block_roots = match maybe_block_roots {
Ok(block_roots) => block_roots,
Err(e) => {
error!(self.log, "Error during iteration over blocks"; "error" => format!("{:?}", e));
return;
}
};
// remove all skip slots
let block_roots = block_roots

View File

@@ -17,6 +17,7 @@ use rest_types::ValidatorSubscription;
use slog::{debug, error, info, o, trace};
use std::sync::Arc;
use std::time::Duration;
use store::HotColdDB;
use tokio::sync::mpsc;
use tokio::time::Delay;
use types::EthSpec;
@@ -40,7 +41,7 @@ pub struct NetworkService<T: BeaconChainTypes> {
/// lighthouse.
router_send: mpsc::UnboundedSender<RouterMessage<T::EthSpec>>,
/// A reference to lighthouse's database to persist the DHT.
store: Arc<T::Store>,
store: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
/// A collection of global variables, accessible outside of the network service.
network_globals: Arc<NetworkGlobals<T::EthSpec>>,
/// A delay that expires when a new fork takes place.
@@ -78,7 +79,7 @@ impl<T: BeaconChainTypes> NetworkService<T> {
let (network_globals, mut libp2p) =
LibP2PService::new(executor.clone(), config, enr_fork_id, &network_log)?;
for enr in load_dht::<T::Store, T::EthSpec>(store.clone()) {
for enr in load_dht::<T::EthSpec, T::HotStore, T::ColdStore>(store.clone()) {
libp2p.swarm.add_enr(enr);
}
@@ -142,7 +143,7 @@ fn spawn_service<T: BeaconChainTypes>(
"Number of peers" => format!("{}", enrs.len()),
);
match persist_dht::<T::Store, T::EthSpec>(service.store.clone(), enrs) {
match persist_dht::<T::EthSpec, T::HotStore, T::ColdStore>(service.store.clone(), enrs) {
Err(e) => error!(
service.log,
"Failed to persist DHT on drop";

View File

@@ -9,6 +9,7 @@ mod tests {
use sloggers::{null::NullLoggerBuilder, Build};
use std::str::FromStr;
use std::sync::Arc;
use store::config::StoreConfig;
use tokio::runtime::Runtime;
use types::{test_utils::generate_deterministic_keypairs, MinimalEthSpec};
@@ -22,7 +23,12 @@ mod tests {
let log = get_logger();
let beacon_chain = Arc::new(
BeaconChainHarness::new(MinimalEthSpec, generate_deterministic_keypairs(8)).chain,
BeaconChainHarness::new(
MinimalEthSpec,
generate_deterministic_keypairs(8),
StoreConfig::default(),
)
.chain,
);
let store = beacon_chain.store.clone();

View File

@@ -265,15 +265,18 @@ impl<T: BeaconChainTypes> SyncManager<T> {
"local_finalized_epoch" => local_peer_info.finalized_epoch,
);
// if we don't know about the peer's chain add it to the range sync, otherwise
// consider it synced (it can be the case that the peer seems ahead of us, but we
// reject its chain).
// There are few cases to handle here:
//
// - A peer could appear advanced if our fork choice has rejected their version of
// the chain. If we know of their head slot, we consider this peer fully synced.
// - A peer could have just advanced to the next epoch and have a new finalized
// epoch that is currently ahead of ours. If their finalized epoch is ahead of ours
// by one and their head_slot is within the slot tolerance, consider this peer
// fully synced.
if self
.chain
.fork_choice
.read()
.contains_block(&remote.head_root)
if (self.chain.fork_choice.read().contains_block(&remote.head_root)) || // the first case
(remote.finalized_epoch.sub(local_peer_info.finalized_epoch) == 1 && remote.head_slot.sub(local_peer_info.head_slot) < SLOT_IMPORT_TOLERANCE as u64)
// the second case
{
self.synced_peer(&peer_id, remote);
// notify the range sync that a peer has been added
@@ -554,7 +557,7 @@ impl<T: BeaconChainTypes> SyncManager<T> {
self.update_sync_state();
}
/// Updates the syncing state of a peer to be behind.
/// Updates the syncing state of a peer to be advanced.
fn advanced_peer(&mut self, peer_id: &PeerId, sync_info: PeerSyncInfo) {
if let Some(peer_info) = self.network_globals.peers.write().peer_info_mut(peer_id) {
let head_slot = sync_info.head_slot;

View File

@@ -21,7 +21,7 @@ pub struct PeerSyncInfo {
pub enum PeerSyncType {
/// The peer is on our chain and is fully synced with respect to our chain.
FullySynced,
/// The peer has a greater knowledge of the chain that us that warrants a full sync.
/// The peer has a greater knowledge of the chain than us that warrants a full sync.
Advanced,
/// A peer is behind in the sync and not useful to us for downloading blocks.
Behind,
@@ -56,8 +56,8 @@ impl PeerSyncInfo {
Some(Self::from(status_message(chain)?))
}
/// Given another peer's `PeerSyncInfo` this will determine how useful that peer is for us in
/// regards to syncing. This returns the peer sync type that can then be handled by the
/// Given another peer's `PeerSyncInfo` this will determine how useful that peer is to us in
/// regards to syncing. This returns the peer sync type that can then be handled by the
/// `SyncManager`.
pub fn peer_sync_type(&self, remote_peer_sync_info: &PeerSyncInfo) -> PeerSyncType {
// check if the peer is fully synced with our current chain