Implement freezer database (#508)

* Implement freezer database for state vectors

* Improve BeaconState safe accessors

And fix a bug in the compact committees accessor.

* Banish dodgy type bounds back to gRPC

* Clean up

* Switch to exclusive end points in chunked vec

* Cleaning up and start of tests

* Randao fix, more tests

* Fix unsightly hack

* Resolve test FIXMEs

* Config file support

* More clean-ups, migrator beginnings

* Finish migrator, integrate into BeaconChain

* Fixups

* Fix store tests

* Fix BeaconChain tests

* Fix LMD GHOST tests

* Address review comments, delete 'static bounds

* Cargo format

* Address review comments

* Fix LMD ghost tests

* Update to spec v0.9.0

* Update to v0.9.1

* Bump spec tags for v0.9.1

* Formatting, fix CI failures

* Resolve accidental KeyPair merge conflict

* Document new BeaconState functions

* Fix incorrect cache drops in `advance_caches`

* Update fork choice for v0.9.1

* Clean up some FIXMEs

* Fix a few docs/logs

* Update for new builder paradigm, spec changes

* Freezer DB integration into BeaconNode

* Cleaning up

* This works, clean it up

* Cleanups

* Fix and improve store tests

* Refine store test

* Delete unused beacon_chain_builder.rs

* Fix CLI

* Store state at split slot in hot database

* Make fork choice lookup fast again

* Store freezer DB split slot in the database

* Handle potential div by 0 in chunked_vector

* Exclude committee caches from freezer DB

* Remove FIXME about long-running test
This commit is contained in:
Michael Sproul
2019-11-27 10:54:46 +11:00
committed by Paul Hauner
parent a514968155
commit bf2eeae3f2
36 changed files with 2486 additions and 580 deletions

View File

@@ -17,6 +17,14 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.takes_value(true)
.global(true)
)
.arg(
Arg::with_name("freezer-dir")
.long("freezer-dir")
.value_name("DIR")
.help("Data directory for the freezer database.")
.takes_value(true)
.global(true)
)
/*
* Network parameters.
*/

View File

@@ -306,7 +306,7 @@ impl ConfigBuilder {
///
/// - Client config
/// - Eth2 config
/// - The entire database directory
/// - All database directories
pub fn clean_datadir(&mut self) -> Result<()> {
let backup_dir = {
let mut s = String::from("backup_");
@@ -334,10 +334,8 @@ impl ConfigBuilder {
move_to_backup_dir(&self.client_config.data_dir.join(CLIENT_CONFIG_FILENAME))?;
move_to_backup_dir(&self.client_config.data_dir.join(ETH2_CONFIG_FILENAME))?;
if let Some(db_path) = self.client_config.db_path() {
move_to_backup_dir(&db_path)?;
}
move_to_backup_dir(&self.client_config.create_db_path()?)?;
move_to_backup_dir(&self.client_config.create_freezer_db_path()?)?;
Ok(())
}
@@ -475,7 +473,7 @@ impl ConfigBuilder {
pub fn write_configs_to_new_datadir(&mut self) -> Result<()> {
let db_exists = self
.client_config
.db_path()
.get_db_path()
.map(|d| d.exists())
.unwrap_or_else(|| false);
@@ -531,19 +529,22 @@ impl ConfigBuilder {
//
// For now we return an error. In the future we may decide to boot a default (e.g.,
// public testnet or mainnet).
if !self.client_config.data_dir.exists() {
if !self
.client_config
.get_data_dir()
.map_or(false, |d| d.exists())
{
return Err(
"No datadir found. Either create a new testnet or specify a different `--datadir`."
.into(),
);
}
// If there is a path to a databse in the config, ensure it exists.
// If there is a path to a database in the config, ensure it exists.
if !self
.client_config
.db_path()
.map(|path| path.exists())
.unwrap_or_else(|| true)
.get_db_path()
.map_or(false, |path| path.exists())
{
return Err(
"No database found in datadir. Use 'testnet -f' to overwrite the existing \

View File

@@ -19,13 +19,14 @@ use environment::RuntimeContext;
use futures::{Future, IntoFuture};
use slog::{info, warn};
use std::ops::{Deref, DerefMut};
use store::DiskStore;
use store::{migrate::BackgroundMigrator, DiskStore};
use types::EthSpec;
/// A type-alias to the tighten the definition of a production-intended `Client`.
pub type ProductionClient<E> = Client<
Witness<
DiskStore,
BackgroundMigrator<E>,
SystemTimeSlotClock,
ThreadSafeReducedTree<DiskStore, E>,
CachingEth1Backend<E, DiskStore>,
@@ -80,15 +81,17 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
let client_genesis = client_config.genesis.clone();
let log = context.log.clone();
client_config
.db_path()
.ok_or_else(|| "Unable to access database path".to_string())
let db_path_res = client_config.create_db_path();
let freezer_db_path_res = client_config.create_freezer_db_path();
db_path_res
.into_future()
.and_then(move |db_path| {
Ok(ClientBuilder::new(context.eth_spec_instance.clone())
.runtime_context(context)
.disk_store(&db_path)?
.chain_spec(spec))
.chain_spec(spec)
.disk_store(&db_path, &freezer_db_path_res?)?
.background_migrator()?)
})
.and_then(move |builder| {
builder.beacon_chain_builder(client_genesis, genesis_eth1_config)