Skip to content
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

[Merged by Bors] - Switch default slasher backend to LMDB #4360

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ test-op-pool-%:

# Run the tests in the `slasher` crate for all supported database backends.
test-slasher:
cargo test --release -p slasher --features mdbx
cargo test --release -p slasher --no-default-features --features lmdb
cargo test --release -p slasher --features lmdb
cargo test --release -p slasher --no-default-features --features mdbx
cargo test --release -p slasher --features lmdb,mdbx # both backends enabled

# Runs only the tests/state_transition_vectors tests.
run-state-transition-tests:
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ clap_utils = { path = "../common/clap_utils" }
hyper = "0.14.4"
lighthouse_version = { path = "../common/lighthouse_version" }
hex = "0.4.2"
slasher = { path = "../slasher", default-features = false }
slasher = { path = "../slasher" }
monitoring_api = { path = "../common/monitoring_api" }
sensitive_url = { path = "../common/sensitive_url" }
http_api = { path = "http_api" }
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fork_choice = { path = "../../consensus/fork_choice" }
task_executor = { path = "../../common/task_executor" }
derivative = "2.1.1"
itertools = "0.10.0"
slasher = { path = "../../slasher", default-features = false }
slasher = { path = "../../slasher" }
eth2 = { path = "../../common/eth2" }
strum = { version = "0.24.0", features = ["derive"] }
logging = { path = "../../common/logging" }
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ time = "0.3.5"
directory = {path = "../../common/directory"}
http_api = { path = "../http_api" }
http_metrics = { path = "../http_metrics" }
slasher = { path = "../../slasher", default-features = false }
slasher = { path = "../../slasher" }
slasher_service = { path = "../../slasher/service" }
monitoring_api = {path = "../../common/monitoring_api"}
execution_layer = { path = "../execution_layer" }
24 changes: 22 additions & 2 deletions beacon_node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub use client::{Client, ClientBuilder, ClientConfig, ClientGenesis};
pub use config::{get_config, get_data_dir, get_slots_per_restore_point, set_network_config};
use environment::RuntimeContext;
pub use eth2_config::Eth2Config;
use slasher::Slasher;
use slasher::{DatabaseBackendOverride, Slasher};
use slog::{info, warn};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
Expand Down Expand Up @@ -86,7 +86,27 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
.http_api_config(client_config.http_api.clone())
.disk_store(&db_path, &freezer_db_path, store_config, log.clone())?;

let builder = if let Some(slasher_config) = client_config.slasher.clone() {
let builder = if let Some(mut slasher_config) = client_config.slasher.clone() {
match slasher_config.override_backend() {
DatabaseBackendOverride::Success(old_backend) => {
info!(
log,
"Slasher backend overriden";
"reason" => "database exists",
"configured_backend" => %old_backend,
"override_backend" => %slasher_config.backend,
);
}
DatabaseBackendOverride::Failure(path) => {
warn!(
log,
"Slasher backend override failed";
"advice" => "delete old MDBX database or enable MDBX backend",
"path" => path.display()
);
}
_ => {}
}
let slasher = Arc::new(
Slasher::open(slasher_config, log.new(slog::o!("service" => "slasher")))
.map_err(|e| format!("Slasher open error: {:?}", e))?,
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ beacon_chain = {path = "../beacon_chain"}

[dependencies]
db-key = "0.0.5"
leveldb = { version = "0.8.6", default-features = false }
leveldb = { version = "0.8.6" }
parking_lot = "0.12.0"
itertools = "0.10.0"
ethereum_ssz = "0.5.0"
Expand Down
12 changes: 6 additions & 6 deletions book/src/installation-source.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ the instructions below, and then proceed to [Building Lighthouse](#build-lightho

## Dependencies

First, **install Rust** using [rustup](https://rustup.rs/):
First, **install Rust** using [rustup](https://rustup.rs/):

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Expand Down Expand Up @@ -64,10 +64,10 @@ After this, you are ready to [build Lighthouse](#build-lighthouse).

1. Install [Git](https://git-scm.com/download/win).
1. Install the [Chocolatey](https://chocolatey.org/install) package manager for Windows.
> Tips:
> Tips:
> - Use PowerShell to install. In Windows, search for PowerShell and run as administrator.
> - You must ensure `Get-ExecutionPolicy` is not Restricted. To test this, run `Get-ExecutionPolicy` in PowerShell. If it returns `restricted`, then run `Set-ExecutionPolicy AllSigned`, and then run
```bash
```bash
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
```
> - To verify that Chocolatey is ready, run `choco` and it should return the version.
Expand Down Expand Up @@ -159,13 +159,13 @@ Commonly used features include:
* `gnosis`: support for the Gnosis Beacon Chain.
* `portable`: support for legacy hardware.
* `modern`: support for exclusively modern hardware.
* `slasher-mdbx`: support for the MDBX slasher backend. Enabled by default.
* `slasher-lmdb`: support for the LMDB slasher backend.
* `slasher-lmdb`: support for the LMDB slasher backend. Enabled by default.
* `slasher-mdbx`: support for the MDBX slasher backend.
* `jemalloc`: use [`jemalloc`][jemalloc] to allocate memory. Enabled by default on Linux and macOS.
Not supported on Windows.
* `spec-minimal`: support for the minimal preset (useful for testing).

Default features (e.g. `slasher-mdbx`) may be opted out of using the `--no-default-features`
Default features (e.g. `slasher-lmdb`) may be opted out of using the `--no-default-features`
argument for `cargo`, which can be plumbed in via the `CARGO_INSTALL_EXTRA_FLAGS` environment variable.
E.g.

Expand Down
44 changes: 35 additions & 9 deletions book/src/slasher.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,49 @@ directory.

* Flag: `--slasher-backend NAME`
* Argument: one of `mdbx`, `lmdb` or `disabled`
* Default: `mdbx`
* Default: `lmdb` for new installs, `mdbx` if an MDBX database already exists

Since Lighthouse v2.6.0 it is possible to use one of several database backends with the slasher:
It is possible to use one of several database backends with the slasher:

- MDBX (default)
- LMDB
- LMDB (default)
- MDBX

The advantage of MDBX is that it performs compaction, resulting in less disk usage over time. The
disadvantage is that upstream MDBX has removed support for Windows and macOS, so Lighthouse is stuck
on an older version. If bugs are found in our pinned version of MDBX it may be deprecated in future.
disadvantage is that upstream MDBX is unstable, so Lighthouse is pinned to a specific version.
If bugs are found in our pinned version of MDBX it may be deprecated in future.

LMDB does not have compaction but is more stable upstream than MDBX. It is not currently recommended
to use the LMDB backend on Windows.
LMDB does not have compaction but is more stable upstream than MDBX. If running with the LMDB
backend on Windows it is recommended to allow extra space due to this issue:
[sigp/lighthouse#2342](https://github.com/sigp/lighthouse/issues/2342).

More backends may be added in future.

### Switching Backends
#### Backend Override

The default backend was changed from MDBX to LMDB in Lighthouse v4.3.0.

If an MDBX database is already found on disk, then Lighthouse will try to use it. This will result
in a log at start-up:

```
INFO Slasher backend overriden reason: database exists, configured_backend: lmdb, overriden_backend: mdbx
```

If the running Lighthouse binary doesn't have the MDBX backend enabled but an existing database is
found, then a warning will be logged and Lighthouse will continue using the LMDB backend:
michaelsproul marked this conversation as resolved.
Show resolved Hide resolved

```
WARN Slasher backend override failed advice: delete old MDBX database or enable MDBX backend, path: /home/user/.lighthouse/mainnet/beacon/slasher_db/mdbx.dat
```

In this case you should either obtain a Lighthouse binary with the MDBX backend enabled, or delete
the files for the old backend. The pre-built Lighthouse binaries and Docker images have MDBX enabled,
or if you're [building from source](./installation-source.md) you can enable the `slasher-mdbx` feature.

To delete the files, use the `path` from the `WARN` log, and then delete the `mbdx.dat` and
`mdbx.lck` files.

#### Switching Backends

If you change database backends and want to reclaim the space used by the old backend you can
delete the following files from your `slasher_db` directory:
Expand Down
4 changes: 2 additions & 2 deletions lighthouse/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ autotests = false
rust-version = "1.68.2"

[features]
default = ["slasher-mdbx"]
default = ["slasher-lmdb"]
# Writes debugging .ssz files to /tmp during block processing.
write_ssz_files = ["beacon_node/write_ssz_files"]
# Compiles the BLS crypto code so that the binary is portable across machines.
Expand Down Expand Up @@ -55,7 +55,7 @@ malloc_utils = { path = "../common/malloc_utils" }
directory = { path = "../common/directory" }
unused_port = { path = "../common/unused_port" }
database_manager = { path = "../database_manager" }
slasher = { path = "../slasher", default-features = false }
slasher = { path = "../slasher" }

[dev-dependencies]
tempfile = "3.1.0"
Expand Down
6 changes: 3 additions & 3 deletions lighthouse/tests/beacon_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1903,7 +1903,7 @@ fn slasher_backend_default() {
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config.slasher.as_ref().unwrap();
assert_eq!(slasher_config.backend, slasher::DatabaseBackend::Mdbx);
assert_eq!(slasher_config.backend, slasher::DatabaseBackend::Lmdb);
});
}

Expand All @@ -1913,11 +1913,11 @@ fn slasher_backend_override_to_default() {
// called "disabled" results in a panic.
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-backend", Some("mdbx"))
.flag("slasher-backend", Some("lmdb"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config.slasher.as_ref().unwrap();
assert_eq!(slasher_config.backend, slasher::DatabaseBackend::Mdbx);
assert_eq!(slasher_config.backend, slasher::DatabaseBackend::Lmdb);
});
}

Expand Down
2 changes: 1 addition & 1 deletion slasher/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors = ["Michael Sproul <[email protected]>"]
edition = "2021"

[features]
default = ["mdbx"]
default = ["lmdb"]
mdbx = ["dep:mdbx"]
lmdb = ["lmdb-rkv", "lmdb-rkv-sys"]

Expand Down
2 changes: 1 addition & 1 deletion slasher/service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ beacon_chain = { path = "../../beacon_node/beacon_chain" }
directory = { path = "../../common/directory" }
lighthouse_network = { path = "../../beacon_node/lighthouse_network" }
network = { path = "../../beacon_node/network" }
slasher = { path = "..", default-features = false }
slasher = { path = ".." }
slog = "2.5.2"
slot_clock = { path = "../../common/slot_clock" }
state_processing = { path = "../../consensus/state_processing" }
Expand Down
36 changes: 34 additions & 2 deletions slasher/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ pub const DEFAULT_MAX_DB_SIZE: usize = 256 * 1024; // 256 GiB
pub const DEFAULT_ATTESTATION_ROOT_CACHE_SIZE: usize = 100_000;
pub const DEFAULT_BROADCAST: bool = false;

#[cfg(feature = "mdbx")]
#[cfg(all(feature = "mdbx", not(feature = "lmdb")))]
pub const DEFAULT_BACKEND: DatabaseBackend = DatabaseBackend::Mdbx;
#[cfg(all(feature = "lmdb", not(feature = "mdbx")))]
#[cfg(feature = "lmdb")]
pub const DEFAULT_BACKEND: DatabaseBackend = DatabaseBackend::Lmdb;
#[cfg(not(any(feature = "mdbx", feature = "lmdb")))]
pub const DEFAULT_BACKEND: DatabaseBackend = DatabaseBackend::Disabled;

pub const MAX_HISTORY_LENGTH: usize = 1 << 16;
pub const MEGABYTE: usize = 1 << 20;
pub const MDBX_DATA_FILENAME: &str = "mdbx.dat";

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
Expand Down Expand Up @@ -64,6 +65,13 @@ pub enum DatabaseBackend {
Disabled,
}

#[derive(Debug, PartialEq)]
pub enum DatabaseBackendOverride {
Success(DatabaseBackend),
Failure(PathBuf),
Noop,
}

impl Config {
pub fn new(database_path: PathBuf) -> Self {
Self {
Expand Down Expand Up @@ -161,4 +169,28 @@ impl Config {
.filter(move |v| self.validator_chunk_index(**v) == validator_chunk_index)
.copied()
}

pub fn override_backend(&mut self) -> DatabaseBackendOverride {
let mdbx_path = self.database_path.join(MDBX_DATA_FILENAME);

#[cfg(feature = "mdbx")]
let already_mdbx = self.backend == DatabaseBackend::Mdbx;
#[cfg(not(feature = "mdbx"))]
let already_mdbx = false;

if !already_mdbx && mdbx_path.exists() {
#[cfg(feature = "mdbx")]
{
let old_backend = self.backend;
self.backend = DatabaseBackend::Mdbx;
DatabaseBackendOverride::Success(old_backend)
}
#[cfg(not(feature = "mdbx"))]
{
DatabaseBackendOverride::Failure(mdbx_path)
}
} else {
DatabaseBackendOverride::Noop
}
}
}
2 changes: 1 addition & 1 deletion slasher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use crate::slasher::Slasher;
pub use attestation_queue::{AttestationBatch, AttestationQueue, SimpleBatch};
pub use attester_record::{AttesterRecord, CompactAttesterRecord, IndexedAttesterRecord};
pub use block_queue::BlockQueue;
pub use config::{Config, DatabaseBackend};
pub use config::{Config, DatabaseBackend, DatabaseBackendOverride};
pub use database::{
interface::{Database, Environment, RwTransaction},
IndexedAttestationId, SlasherDB,
Expand Down
57 changes: 57 additions & 0 deletions slasher/tests/backend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#![cfg(any(feature = "mdbx", feature = "lmdb"))]

use slasher::{config::MDBX_DATA_FILENAME, Config, DatabaseBackend, DatabaseBackendOverride};
use std::fs::File;
use tempfile::tempdir;

#[test]
#[cfg(all(feature = "mdbx", feature = "lmdb"))]
fn override_no_existing_db() {
let tempdir = tempdir().unwrap();
let mut config = Config::new(tempdir.path().into());
assert_eq!(config.override_backend(), DatabaseBackendOverride::Noop);
}

#[test]
#[cfg(all(feature = "mdbx", feature = "lmdb"))]
fn override_with_existing_mdbx_db() {
let tempdir = tempdir().unwrap();
let mut config = Config::new(tempdir.path().into());

File::create(config.database_path.join(MDBX_DATA_FILENAME)).unwrap();

assert_eq!(
config.override_backend(),
DatabaseBackendOverride::Success(DatabaseBackend::Lmdb)
);
assert_eq!(config.backend, DatabaseBackend::Mdbx);
}

#[test]
#[cfg(all(feature = "mdbx", feature = "lmdb"))]
fn no_override_with_existing_mdbx_db() {
let tempdir = tempdir().unwrap();
let mut config = Config::new(tempdir.path().into());
config.backend = DatabaseBackend::Mdbx;

File::create(config.database_path.join(MDBX_DATA_FILENAME)).unwrap();

assert_eq!(config.override_backend(), DatabaseBackendOverride::Noop);
assert_eq!(config.backend, DatabaseBackend::Mdbx);
}

#[test]
#[cfg(all(not(feature = "mdbx"), feature = "lmdb"))]
fn failed_override_with_existing_mdbx_db() {
let tempdir = tempdir().unwrap();
let mut config = Config::new(tempdir.path().into());

let filename = config.database_path.join(MDBX_DATA_FILENAME);
File::create(&filename).unwrap();

assert_eq!(
config.override_backend(),
DatabaseBackendOverride::Failure(filename)
);
assert_eq!(config.backend, DatabaseBackend::Lmdb);
}