diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 416179445f..86f99b53e1 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -258,8 +258,8 @@ jobs:
|
| x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-unknown-linux-gnu-portable.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-unknown-linux-gnu-portable.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-unknown-linux-gnu-portable.tar.gz.asc) |
|
| aarch64 | [lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz.asc) |
|
| aarch64 | [lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu-portable.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu-portable.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-aarch64-unknown-linux-gnu-portable.tar.gz.asc) |
- |
| x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz.asc) |
- |
| x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-windows-portable.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows-portable.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows-portable.tar.gz.asc) |
+ |
| x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows.tar.gz.asc) |
+ |
| x86_64 | [lighthouse-${{ env.VERSION }}-x86_64-windows-portable.tar.gz](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows-portable.tar.gz) | [PGP Signature](https://github.com/${{ env.REPO_NAME }}/releases/download/${{ env.VERSION }}/lighthouse-${{ env.VERSION }}-x86_64-windows-portable.tar.gz.asc) |
| | | | |
| **System** | **Option** | - | **Resource** |
|
| Docker | [${{ env.VERSION }}](https://hub.docker.com/r/${{ env.IMAGE_NAME }}/tags?page=1&ordering=last_updated&name=${{ env.VERSION }}) | [${{ env.IMAGE_NAME }}](https://hub.docker.com/r/${{ env.IMAGE_NAME }}) |
diff --git a/Cargo.lock b/Cargo.lock
index 90196ea5b3..28f1284068 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -855,7 +855,7 @@ dependencies = [
[[package]]
name = "beacon_node"
-version = "5.2.0"
+version = "5.2.1"
dependencies = [
"beacon_chain",
"clap",
@@ -918,21 +918,22 @@ dependencies = [
[[package]]
name = "bindgen"
-version = "0.59.2"
+version = "0.69.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
+checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.5.0",
"cexpr",
"clang-sys",
+ "itertools",
"lazy_static",
"lazycell",
- "peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
+ "syn 2.0.66",
]
[[package]]
@@ -1061,7 +1062,7 @@ dependencies = [
[[package]]
name = "boot_node"
-version = "5.2.0"
+version = "5.2.1"
dependencies = [
"beacon_node",
"clap",
@@ -1168,21 +1169,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "cached_tree_hash"
-version = "0.1.0"
-dependencies = [
- "ethereum-types 0.14.1",
- "ethereum_hashing",
- "ethereum_ssz",
- "ethereum_ssz_derive",
- "quickcheck",
- "quickcheck_macros",
- "smallvec",
- "ssz_types",
- "tree_hash",
-]
-
[[package]]
name = "camino"
version = "1.1.7"
@@ -1354,6 +1340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
+ "clap_derive",
]
[[package]]
@@ -1369,6 +1356,18 @@ dependencies = [
"terminal_size",
]
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+]
+
[[package]]
name = "clap_lex"
version = "0.7.0"
@@ -1838,6 +1837,7 @@ dependencies = [
"clap_utils",
"environment",
"hex",
+ "serde",
"slog",
"store",
"strum",
@@ -2083,7 +2083,7 @@ dependencies = [
"enr",
"fnv",
"futures",
- "hashlink",
+ "hashlink 0.8.4",
"hex",
"hkdf",
"lazy_static",
@@ -3371,6 +3371,7 @@ dependencies = [
"futures-ticker",
"futures-timer",
"getrandom",
+ "hashlink 0.9.0",
"hex_fmt",
"libp2p",
"prometheus-client",
@@ -3486,6 +3487,15 @@ dependencies = [
"hashbrown 0.14.5",
]
+[[package]]
+name = "hashlink"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee"
+dependencies = [
+ "hashbrown 0.14.5",
+]
+
[[package]]
name = "headers"
version = "0.3.9"
@@ -4322,7 +4332,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lcli"
-version = "5.2.0"
+version = "5.2.1"
dependencies = [
"account_utils",
"beacon_chain",
@@ -4427,7 +4437,7 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "libmdbx"
version = "0.1.4"
-source = "git+https://github.com/sigp/libmdbx-rs?tag=v0.1.4#096da80a83d14343f8df833006483f48075cd135"
+source = "git+https://github.com/sigp/libmdbx-rs?rev=e6ff4b9377c1619bcf0bfdf52bee5a980a432a1a#e6ff4b9377c1619bcf0bfdf52bee5a980a432a1a"
dependencies = [
"bitflags 1.3.2",
"byteorder",
@@ -4893,7 +4903,7 @@ dependencies = [
[[package]]
name = "lighthouse"
-version = "5.2.0"
+version = "5.2.1"
dependencies = [
"account_manager",
"account_utils",
@@ -5181,7 +5191,7 @@ dependencies = [
[[package]]
name = "mdbx-sys"
version = "0.11.6-4"
-source = "git+https://github.com/sigp/libmdbx-rs?tag=v0.1.4#096da80a83d14343f8df833006483f48075cd135"
+source = "git+https://github.com/sigp/libmdbx-rs?rev=e6ff4b9377c1619bcf0bfdf52bee5a980a432a1a#e6ff4b9377c1619bcf0bfdf52bee5a980a432a1a"
dependencies = [
"bindgen",
"cc",
@@ -6000,12 +6010,6 @@ dependencies = [
"sha2 0.10.8",
]
-[[package]]
-name = "peeking_take_while"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
-
[[package]]
name = "pem"
version = "1.1.1"
@@ -6678,6 +6682,15 @@ dependencies = [
"yasna",
]
+[[package]]
+name = "redb"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed7508e692a49b6b2290b56540384ccae9b1fb4d77065640b165835b56ffe3bb"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -6967,7 +6980,7 @@ dependencies = [
"bitflags 1.3.2",
"fallible-iterator",
"fallible-streaming-iterator",
- "hashlink",
+ "hashlink 0.8.4",
"libsqlite3-sys",
"smallvec",
]
@@ -7635,6 +7648,7 @@ version = "0.1.0"
dependencies = [
"bincode",
"byteorder",
+ "derivative",
"ethereum_ssz",
"ethereum_ssz_derive",
"filesystem",
@@ -7650,6 +7664,7 @@ dependencies = [
"parking_lot 0.12.3",
"rand",
"rayon",
+ "redb",
"safe_arith",
"serde",
"slog",
@@ -7813,6 +7828,9 @@ name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+dependencies = [
+ "arbitrary",
+]
[[package]]
name = "snap"
@@ -7931,10 +7949,12 @@ dependencies = [
"lazy_static",
"lighthouse_metrics",
"merkle_proof",
+ "rand",
"rayon",
"safe_arith",
"smallvec",
"ssz_types",
+ "test_random_derive",
"tokio",
"tree_hash",
"types",
@@ -8765,7 +8785,6 @@ dependencies = [
"arbitrary",
"beacon_chain",
"bls",
- "cached_tree_hash",
"compare_fields",
"compare_fields_derive",
"criterion",
@@ -9778,7 +9797,7 @@ checksum = "498f4d102a79ea1c9d4dd27573c0fc96ad74c023e8da38484e47883076da25fb"
dependencies = [
"arraydeque",
"encoding_rs",
- "hashlink",
+ "hashlink 0.8.4",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index d67f6edf1d..a76ee7e236 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -51,7 +51,6 @@ members = [
"database_manager",
- "consensus/cached_tree_hash",
"consensus/int_to_bytes",
"consensus/fork_choice",
"consensus/proto_array",
@@ -102,7 +101,7 @@ bincode = "1"
bitvec = "1"
byteorder = "1"
bytes = "1"
-clap = { version = "4.5.4", features = ["cargo", "wrap_help"] }
+clap = { version = "4.5.4", features = ["derive", "cargo", "wrap_help"] }
# Turn off c-kzg's default features which include `blst/portable`. We can turn on blst's portable
# feature ourselves when desired.
c-kzg = { version = "1", default-features = false }
@@ -127,6 +126,7 @@ fnv = "1"
fs2 = "0.4"
futures = "0.3"
hex = "0.4"
+hashlink = "0.9.0"
hyper = "1"
itertools = "0.10"
lazy_static = "1"
@@ -158,7 +158,7 @@ slog = { version = "2", features = ["max_level_trace", "release_max_level_trace"
slog-async = "2"
slog-term = "2"
sloggers = { version = "2", features = ["json"] }
-smallvec = "1.11.2"
+smallvec = { version = "1.11.2", features = ["arbitrary"] }
snap = "1"
ssz_types = "0.6"
strum = { version = "0.24", features = ["derive"] }
@@ -188,7 +188,6 @@ beacon_chain = { path = "beacon_node/beacon_chain" }
beacon_node = { path = "beacon_node" }
beacon_processor = { path = "beacon_node/beacon_processor" }
bls = { path = "crypto/bls" }
-cached_tree_hash = { path = "consensus/cached_tree_hash" }
clap_utils = { path = "common/clap_utils" }
compare_fields = { path = "common/compare_fields" }
deposit_contract = { path = "common/deposit_contract" }
diff --git a/Dockerfile b/Dockerfile
index e0c48699bf..ff7f14d534 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,8 +4,8 @@ COPY . lighthouse
ARG FEATURES
ARG PROFILE=release
ARG CARGO_USE_GIT_CLI=true
-ENV FEATURES $FEATURES
-ENV PROFILE $PROFILE
+ENV FEATURES=$FEATURES
+ENV PROFILE=$PROFILE
ENV CARGO_NET_GIT_FETCH_WITH_CLI=$CARGO_USE_GIT_CLI
RUN cd lighthouse && make
diff --git a/Makefile b/Makefile
index c3c8d13238..d18a673880 100644
--- a/Makefile
+++ b/Makefile
@@ -14,16 +14,8 @@ BUILD_PATH_AARCH64 = "target/$(AARCH64_TAG)/release"
PINNED_NIGHTLY ?= nightly
CLIPPY_PINNED_NIGHTLY=nightly-2022-05-19
-# List of features to use when building natively. Can be overridden via the environment.
-# No jemalloc on Windows
-ifeq ($(OS),Windows_NT)
- FEATURES?=
-else
- FEATURES?=jemalloc
-endif
-
# List of features to use when cross-compiling. Can be overridden via the environment.
-CROSS_FEATURES ?= gnosis,slasher-lmdb,slasher-mdbx,jemalloc
+CROSS_FEATURES ?= gnosis,slasher-lmdb,slasher-mdbx,slasher-redb,jemalloc
# Cargo profile for Cross builds. Default is for local builds, CI uses an override.
CROSS_PROFILE ?= release
@@ -182,8 +174,9 @@ test-network-%:
# Run the tests in the `slasher` crate for all supported database backends.
test-slasher:
cargo nextest run --release -p slasher --features "lmdb,$(TEST_FEATURES)"
+ cargo nextest run --release -p slasher --no-default-features --features "redb,$(TEST_FEATURES)"
cargo nextest run --release -p slasher --no-default-features --features "mdbx,$(TEST_FEATURES)"
- cargo nextest run --release -p slasher --features "lmdb,mdbx,$(TEST_FEATURES)" # both backends enabled
+ cargo nextest run --release -p slasher --features "lmdb,mdbx,redb,$(TEST_FEATURES)" # all backends enabled
# Runs only the tests/state_transition_vectors tests.
run-state-transition-tests:
diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml
index b95720e807..a5fd29c971 100644
--- a/beacon_node/Cargo.toml
+++ b/beacon_node/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "beacon_node"
-version = "5.2.0"
+version = "5.2.1"
authors = [
"Paul Hauner ",
"Age Manning BeaconChain {
Ok(())
}
- pub fn persist_data_availability_checker(&self) -> Result<(), Error> {
- let _timer = metrics::start_timer(&metrics::PERSIST_DATA_AVAILABILITY_CHECKER);
- self.data_availability_checker.persist_all()?;
-
- Ok(())
- }
-
/// Returns the slot _right now_ according to `self.slot_clock`. Returns `Err` if the slot is
/// unavailable.
///
@@ -1410,10 +1403,6 @@ impl BeaconChain {
)
}
- let start_slot = head_state.slot();
- let task_start = Instant::now();
- let max_task_runtime = Duration::from_secs(self.spec.seconds_per_slot);
-
let head_state_slot = head_state.slot();
let mut state = head_state;
@@ -1423,18 +1412,6 @@ impl BeaconChain {
};
while state.slot() < slot {
- // Do not allow and forward state skip that takes longer than the maximum task duration.
- //
- // This is a protection against nodes doing too much work when they're not synced
- // to a chain.
- if task_start + max_task_runtime < Instant::now() {
- return Err(Error::StateSkipTooLarge {
- start_slot,
- requested_slot: slot,
- max_task_runtime,
- });
- }
-
// Note: supplying some `state_root` when it is known would be a cheap and easy
// optimization.
match per_slot_processing(&mut state, skip_state_root, &self.spec) {
@@ -6769,7 +6746,6 @@ impl Drop for BeaconChain {
let drop = || -> Result<(), Error> {
self.persist_head_and_fork_choice()?;
self.persist_op_pool()?;
- self.persist_data_availability_checker()?;
self.persist_eth1_cache()
};
diff --git a/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs b/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs
index f7f389c543..f746b68996 100644
--- a/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs
+++ b/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs
@@ -20,26 +20,12 @@ use types::{
Hash256, Slot,
};
-/// Ensure this justified checkpoint has an epoch of 0 so that it is never
-/// greater than the justified checkpoint and enshrined as the actual justified
-/// checkpoint.
-const JUNK_BEST_JUSTIFIED_CHECKPOINT: Checkpoint = Checkpoint {
- epoch: Epoch::new(0),
- root: Hash256::repeat_byte(0),
-};
-
#[derive(Debug)]
pub enum Error {
- UnableToReadSlot,
- UnableToReadTime,
- InvalidGenesisSnapshot(Slot),
- AncestorUnknown { ancestor_slot: Slot },
- UninitializedBestJustifiedBalances,
FailedToReadBlock(StoreError),
MissingBlock(Hash256),
FailedToReadState(StoreError),
MissingState(Hash256),
- InvalidPersistedBytes(ssz::DecodeError),
BeaconStateError(BeaconStateError),
Arith(ArithError),
}
@@ -66,7 +52,6 @@ const MAX_BALANCE_CACHE_SIZE: usize = 4;
)]
pub(crate) struct CacheItem {
pub(crate) block_root: Hash256,
- #[superstruct(only(V8))]
pub(crate) epoch: Epoch,
pub(crate) balances: Vec,
}
@@ -79,7 +64,6 @@ pub(crate) type CacheItem = CacheItemV8;
no_enum
)]
pub struct BalancesCache {
- #[superstruct(only(V8))]
pub(crate) items: Vec,
}
@@ -365,59 +349,15 @@ where
pub type PersistedForkChoiceStore = PersistedForkChoiceStoreV17;
/// A container which allows persisting the `BeaconForkChoiceStore` to the on-disk database.
-#[superstruct(
- variants(V11, V17),
- variant_attributes(derive(Encode, Decode)),
- no_enum
-)]
+#[superstruct(variants(V17), variant_attributes(derive(Encode, Decode)), no_enum)]
pub struct PersistedForkChoiceStore {
- #[superstruct(only(V11, V17))]
pub balances_cache: BalancesCacheV8,
pub time: Slot,
pub finalized_checkpoint: Checkpoint,
pub justified_checkpoint: Checkpoint,
pub justified_balances: Vec,
- #[superstruct(only(V11))]
- pub best_justified_checkpoint: Checkpoint,
- #[superstruct(only(V11, V17))]
pub unrealized_justified_checkpoint: Checkpoint,
- #[superstruct(only(V11, V17))]
pub unrealized_finalized_checkpoint: Checkpoint,
- #[superstruct(only(V11, V17))]
pub proposer_boost_root: Hash256,
- #[superstruct(only(V11, V17))]
pub equivocating_indices: BTreeSet,
}
-
-impl From for PersistedForkChoiceStore {
- fn from(from: PersistedForkChoiceStoreV11) -> PersistedForkChoiceStore {
- PersistedForkChoiceStore {
- balances_cache: from.balances_cache,
- time: from.time,
- finalized_checkpoint: from.finalized_checkpoint,
- justified_checkpoint: from.justified_checkpoint,
- justified_balances: from.justified_balances,
- unrealized_justified_checkpoint: from.unrealized_justified_checkpoint,
- unrealized_finalized_checkpoint: from.unrealized_finalized_checkpoint,
- proposer_boost_root: from.proposer_boost_root,
- equivocating_indices: from.equivocating_indices,
- }
- }
-}
-
-impl From for PersistedForkChoiceStoreV11 {
- fn from(from: PersistedForkChoiceStore) -> PersistedForkChoiceStoreV11 {
- PersistedForkChoiceStoreV11 {
- balances_cache: from.balances_cache,
- time: from.time,
- finalized_checkpoint: from.finalized_checkpoint,
- justified_checkpoint: from.justified_checkpoint,
- justified_balances: from.justified_balances,
- best_justified_checkpoint: JUNK_BEST_JUSTIFIED_CHECKPOINT,
- unrealized_justified_checkpoint: from.unrealized_justified_checkpoint,
- unrealized_finalized_checkpoint: from.unrealized_finalized_checkpoint,
- proposer_boost_root: from.proposer_boost_root,
- equivocating_indices: from.equivocating_indices,
- }
- }
-}
diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs
index b24921e317..734b12ca83 100644
--- a/beacon_node/beacon_chain/src/block_verification.rs
+++ b/beacon_node/beacon_chain/src/block_verification.rs
@@ -93,7 +93,6 @@ use std::io::Write;
use std::sync::Arc;
use store::{Error as DBError, HotStateSummary, KeyValueStore, StoreOp};
use task_executor::JoinHandle;
-use tree_hash::TreeHash;
use types::{
BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, ExecutionBlockHash,
Hash256, InconsistentFork, PublicKey, PublicKeyBytes, RelativeEpoch, SignedBeaconBlock,
@@ -2107,7 +2106,14 @@ pub fn verify_header_signature(
fn write_state(prefix: &str, state: &BeaconState, log: &Logger) {
if WRITE_BLOCK_PROCESSING_SSZ {
- let root = state.tree_hash_root();
+ let mut state = state.clone();
+ let Ok(root) = state.canonical_root() else {
+ error!(
+ log,
+ "Unable to hash state for writing";
+ );
+ return;
+ };
let filename = format!("{}_slot_{}_root_{}.ssz", prefix, state.slot(), root);
let mut path = std::env::temp_dir().join("lighthouse");
let _ = fs::create_dir_all(path.clone());
diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs
index 90461b8f03..7217f2c640 100644
--- a/beacon_node/beacon_chain/src/builder.rs
+++ b/beacon_node/beacon_chain/src/builder.rs
@@ -1195,7 +1195,7 @@ mod test {
let head = chain.head_snapshot();
- let state = &head.beacon_state;
+ let mut state = head.beacon_state.clone();
let block = &head.beacon_block;
assert_eq!(state.slot(), Slot::new(0), "should start from genesis");
@@ -1206,7 +1206,7 @@ mod test {
);
assert_eq!(
block.state_root(),
- state.canonical_root(),
+ state.canonical_root().unwrap(),
"block should have correct state root"
);
assert_eq!(
diff --git a/beacon_node/beacon_chain/src/data_availability_checker.rs b/beacon_node/beacon_chain/src/data_availability_checker.rs
index e0347d81c3..2431769ddb 100644
--- a/beacon_node/beacon_chain/src/data_availability_checker.rs
+++ b/beacon_node/beacon_chain/src/data_availability_checker.rs
@@ -2,7 +2,7 @@ use crate::blob_verification::{verify_kzg_for_blob_list, GossipVerifiedBlob, Kzg
use crate::block_verification_types::{
AvailabilityPendingExecutedBlock, AvailableExecutedBlock, RpcBlock,
};
-use crate::data_availability_checker::overflow_lru_cache::OverflowLRUCache;
+use crate::data_availability_checker::overflow_lru_cache::DataAvailabilityCheckerInner;
use crate::{BeaconChain, BeaconChainTypes, BeaconStore};
use kzg::Kzg;
use slog::{debug, error, Logger};
@@ -33,12 +33,32 @@ pub const OVERFLOW_LRU_CAPACITY: NonZeroUsize = new_non_zero_usize(1024);
pub const STATE_LRU_CAPACITY_NON_ZERO: NonZeroUsize = new_non_zero_usize(2);
pub const STATE_LRU_CAPACITY: usize = STATE_LRU_CAPACITY_NON_ZERO.get();
-/// This includes a cache for any blocks or blobs that have been received over gossip or RPC
-/// and are awaiting more components before they can be imported. Additionally the
-/// `DataAvailabilityChecker` is responsible for KZG verification of block components as well as
-/// checking whether a "availability check" is required at all.
+/// Cache to hold fully valid data that can't be imported to fork-choice yet. After Dencun hard-fork
+/// blocks have a sidecar of data that is received separately from the network. We call the concept
+/// of a block "becoming available" when all of its import dependencies are inserted into this
+/// cache.
+///
+/// Usually a block becomes available on its slot within a second of receiving its first component
+/// over gossip. However, a block may never become available if a malicious proposer does not
+/// publish its data, or there are network issues that prevent us from receiving it. If the block
+/// does not become available after some time we can safely forget about it. Consider these two
+/// cases:
+///
+/// - Global unavailability: If nobody has received the block components it's likely that the
+/// proposer never made the block available. So we can safely forget about the block as it will
+/// never become available.
+/// - Local unavailability: Some fraction of the network has received all block components, but not us.
+/// Some of our peers will eventually attest to a descendant of that block and lookup sync will
+/// fetch its components. Therefore it's not strictly necessary to hold to the partially available
+/// block for too long as we can recover from other peers.
+///
+/// Even in periods of non-finality, the proposer is expected to publish the block's data
+/// immediately. Because this cache only holds fully valid data, its capacity is bound to 1 block
+/// per slot and fork: before inserting into this cache we check the proposer signature and correct
+/// proposer. Having a capacity > 1 is an optimization to prevent sync lookup from having re-fetch
+/// data during moments of unstable network conditions.
pub struct DataAvailabilityChecker {
- availability_cache: Arc>,
+ availability_cache: Arc>,
slot_clock: T::SlotClock,
kzg: Option>,
log: Logger,
@@ -74,7 +94,8 @@ impl DataAvailabilityChecker {
log: &Logger,
spec: ChainSpec,
) -> Result {
- let overflow_cache = OverflowLRUCache::new(OVERFLOW_LRU_CAPACITY, store, spec.clone())?;
+ let overflow_cache =
+ DataAvailabilityCheckerInner::new(OVERFLOW_LRU_CAPACITY, store, spec.clone())?;
Ok(Self {
availability_cache: Arc::new(overflow_cache),
slot_clock,
@@ -329,15 +350,9 @@ impl DataAvailabilityChecker {
})
}
- /// Persist all in memory components to disk
- pub fn persist_all(&self) -> Result<(), AvailabilityCheckError> {
- self.availability_cache.write_all_to_disk()
- }
-
/// Collects metrics from the data availability checker.
pub fn metrics(&self) -> DataAvailabilityCheckerMetrics {
DataAvailabilityCheckerMetrics {
- num_store_entries: self.availability_cache.num_store_entries(),
state_cache_size: self.availability_cache.state_cache_size(),
block_cache_size: self.availability_cache.block_cache_size(),
}
@@ -346,7 +361,6 @@ impl DataAvailabilityChecker {
/// Helper struct to group data availability checker metrics.
pub struct DataAvailabilityCheckerMetrics {
- pub num_store_entries: usize,
pub state_cache_size: usize,
pub block_cache_size: usize,
}
@@ -372,7 +386,7 @@ pub fn start_availability_cache_maintenance_service(
async fn availability_cache_maintenance_service(
chain: Arc>,
- overflow_cache: Arc>,
+ overflow_cache: Arc>,
) {
let epoch_duration = chain.slot_clock.slot_duration() * T::EthSpec::slots_per_epoch() as u32;
loop {
diff --git a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
index adc1a1e202..5e0513c8d3 100644
--- a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
+++ b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
@@ -1,32 +1,3 @@
-//! This module implements a LRU cache for storing partially available blocks and blobs.
-//! When the cache overflows, the least recently used items are persisted to the database.
-//! This prevents lighthouse from using too much memory storing unfinalized blocks and blobs
-//! if the chain were to lose finality.
-//!
-//! ## Deadlock safety
-//!
-//! The main object in this module is the `OverflowLruCache`. It contains two locks:
-//!
-//! - `self.critical` is an `RwLock` that protects content stored in memory.
-//! - `self.maintenance_lock` is held when moving data between memory and disk.
-//!
-//! You mostly need to ensure that you don't try to hold the critical lock more than once
-//!
-//! ## Basic Algorithm
-//!
-//! As blocks and blobs come in from the network, their components are stored in memory in
-//! this cache. When a block becomes fully available, it is removed from the cache and
-//! imported into fork-choice. Blocks/blobs that remain unavailable will linger in the
-//! cache until they are older than the finalized epoch or older than the data availability
-//! cutoff. In the event the chain is not finalizing, the cache will eventually overflow and
-//! the least recently used items will be persisted to disk. When this happens, we will still
-//! store the hash of the block in memory so we always know we have data for that block
-//! without needing to check the database.
-//!
-//! When the client is shut down, all pending components are persisted in the database.
-//! On startup, the keys of these components are stored in memory and will be loaded in
-//! the cache when they are accessed.
-
use super::state_lru_cache::{DietAvailabilityPendingExecutedBlock, StateLRUCache};
use crate::beacon_chain::BeaconStore;
use crate::blob_verification::KzgVerifiedBlob;
@@ -34,15 +5,13 @@ use crate::block_verification_types::{
AvailabilityPendingExecutedBlock, AvailableBlock, AvailableExecutedBlock,
};
use crate::data_availability_checker::{Availability, AvailabilityCheckError};
-use crate::store::{DBColumn, KeyValueStore};
use crate::BeaconChainTypes;
use lru::LruCache;
-use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
-use ssz::{Decode, Encode};
+use parking_lot::RwLock;
use ssz_derive::{Decode, Encode};
use ssz_types::{FixedVector, VariableList};
use std::num::NonZeroUsize;
-use std::{collections::HashSet, sync::Arc};
+use std::sync::Arc;
use types::blob_sidecar::BlobIdentifier;
use types::{BlobSidecar, ChainSpec, Epoch, EthSpec, Hash256, SignedBeaconBlock};
@@ -243,318 +212,27 @@ impl PendingComponents {
AvailableExecutedBlock::new(available_block, import_data, payload_verification_outcome),
)))
}
-
- /// Returns the epoch of the block if it is cached, otherwise returns the epoch of the first blob.
- pub fn epoch(&self) -> Option {
- self.executed_block
- .as_ref()
- .map(|pending_block| pending_block.as_block().epoch())
- .or_else(|| {
- for maybe_blob in self.verified_blobs.iter() {
- if maybe_blob.is_some() {
- return maybe_blob.as_ref().map(|kzg_verified_blob| {
- kzg_verified_blob
- .as_blob()
- .slot()
- .epoch(E::slots_per_epoch())
- });
- }
- }
- None
- })
- }
-}
-
-/// Blocks and blobs are stored in the database sequentially so that it's
-/// fast to iterate over all the data for a particular block.
-#[derive(Debug, PartialEq)]
-enum OverflowKey {
- Block(Hash256),
- Blob(Hash256, u8),
-}
-
-impl OverflowKey {
- pub fn from_block_root(block_root: Hash256) -> Self {
- Self::Block(block_root)
- }
-
- pub fn from_blob_id(
- blob_id: BlobIdentifier,
- ) -> Result {
- if blob_id.index > E::max_blobs_per_block() as u64 || blob_id.index > u8::MAX as u64 {
- return Err(AvailabilityCheckError::BlobIndexInvalid(blob_id.index));
- }
- Ok(Self::Blob(blob_id.block_root, blob_id.index as u8))
- }
-
- pub fn root(&self) -> &Hash256 {
- match self {
- Self::Block(root) => root,
- Self::Blob(root, _) => root,
- }
- }
-}
-
-/// A wrapper around BeaconStore that implements various
-/// methods used for saving and retrieving blocks / blobs
-/// from the store (for organization)
-struct OverflowStore(BeaconStore);
-
-impl OverflowStore {
- /// Store pending components in the database
- pub fn persist_pending_components(
- &self,
- block_root: Hash256,
- mut pending_components: PendingComponents,
- ) -> Result<(), AvailabilityCheckError> {
- let col = DBColumn::OverflowLRUCache;
-
- if let Some(block) = pending_components.executed_block.take() {
- let key = OverflowKey::from_block_root(block_root);
- self.0
- .hot_db
- .put_bytes(col.as_str(), &key.as_ssz_bytes(), &block.as_ssz_bytes())?
- }
-
- for blob in Vec::from(pending_components.verified_blobs)
- .into_iter()
- .flatten()
- {
- let key = OverflowKey::from_blob_id::(BlobIdentifier {
- block_root,
- index: blob.blob_index(),
- })?;
-
- self.0
- .hot_db
- .put_bytes(col.as_str(), &key.as_ssz_bytes(), &blob.as_ssz_bytes())?
- }
-
- Ok(())
- }
-
- /// Load the pending components that we have in the database for a given block root
- pub fn load_pending_components(
- &self,
- block_root: Hash256,
- ) -> Result