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

Upgrade in-memory and on-disk state representation with tree states #3206

Open
wants to merge 84 commits into
base: unstable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
23db089
Implement tree states & hierarchical state DB
michaelsproul Jun 19, 2023
d56cec8
Address clippy lints in `tree-states` (#4414)
paulhauner Jun 20, 2023
6eb1513
Configurable diff buffer cache size (#4420)
michaelsproul Jun 20, 2023
ca412ab
Use rebasing to minimise BeaconState mem usage (#4416)
michaelsproul Jun 21, 2023
88e30b6
Fix failing tests (#4423)
michaelsproul Jun 27, 2023
7c2eb96
Set epochs per migration to 1
michaelsproul Jun 27, 2023
56c7a52
Install Clang 5 in Cross builder image
michaelsproul Jun 27, 2023
af5fb20
Tree states alpha release v4.2.99-exp
michaelsproul Jun 27, 2023
8dc374e
Temporarily disable ARM builds
michaelsproul Jun 27, 2023
6954de6
Tree states alpha release v4.2.990-exp
michaelsproul Jun 27, 2023
160bbde
Fix db-migration-period default (#4441)
michaelsproul Jun 30, 2023
2df714e
Tree states optimization using `EpochCache` (#4429)
jimmygchen Jun 30, 2023
f631b51
Fix EpochCache handling in ef-tests
michaelsproul Jun 30, 2023
835fa70
Fix EpochCache handling in ef-tests (#4454)
michaelsproul Jun 30, 2023
b414c32
Implement activation queue cache
michaelsproul Jul 3, 2023
0291998
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Jul 3, 2023
079cd67
Merge remote-tracking branch 'origin/tree-states' into tree-states
michaelsproul Jul 3, 2023
5d2063d
Single-pass epoch processing (#4483)
michaelsproul Jul 18, 2023
8423e9f
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Jul 19, 2023
18e64e6
Optimise mutations in single-pass epoch processing (#4573)
michaelsproul Aug 8, 2023
bba1526
Fix deadlock in finalization migration (#4576)
michaelsproul Aug 8, 2023
e373e9a
Fix genesis state storage for genesis sync (#4589)
michaelsproul Aug 9, 2023
1e4ee7a
Tree states to support per-slot state diffs (#4652)
jimmygchen Sep 11, 2023
b8e04ce
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Sep 13, 2023
d961d2c
Disable ARM docker builds
michaelsproul Sep 13, 2023
838e104
Attempt to fix flaky test
michaelsproul Sep 13, 2023
68f80cc
Change default epochs-per-state-diff to 16
michaelsproul Sep 13, 2023
f7c6b7d
Bump schema version to v24
michaelsproul Sep 13, 2023
5cb2ed3
Restore custom image for Cross
michaelsproul Sep 13, 2023
1b4bc88
Release v4.4.111-exp (#4729)
michaelsproul Sep 14, 2023
cd23c89
Improve state cache eviction and reduce mem usage (#4762)
michaelsproul Sep 22, 2023
d24875f
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Sep 22, 2023
364074d
Tree states release v4.5.111-exp (#4769)
michaelsproul Sep 22, 2023
cae73a4
Merge tag 'v4.5.0' into tree-states
michaelsproul Sep 26, 2023
f1f76f2
Tree states release v4.5.222-exp (#4782)
michaelsproul Sep 26, 2023
109c4a5
Merge remote-tracking branch 'origin/deneb-free-blobs' into tree-states
michaelsproul Sep 29, 2023
9446fc8
Fix semantic Deneb <> tree-states conflicts
michaelsproul Oct 3, 2023
e2a60a6
Merge remote-tracking branch 'origin/deneb-free-blobs' into tree-stat…
michaelsproul Oct 6, 2023
ca1abfe
Support iterables in compare_fields
michaelsproul Oct 10, 2023
d4f87ef
Fix three consensus bugs!
michaelsproul Oct 11, 2023
e63d02e
Merge remote-tracking branch 'origin/deneb-free-blobs' into tree-stat…
michaelsproul Oct 11, 2023
6ae4c22
Fix merge snafu in tests
michaelsproul Oct 11, 2023
dfa3b43
Fix Clippy for 1.73
michaelsproul Oct 11, 2023
b77de69
Re-enable ARM builds
michaelsproul Oct 11, 2023
b121e69
Fix cache logic for epoch boundary skips (#4833)
michaelsproul Oct 13, 2023
bb6675e
Clean up progressive balance slashings further (#4834)
michaelsproul Oct 13, 2023
72d8c38
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Oct 19, 2023
0cb8fdf
Various small tree-states fixes (#4861)
michaelsproul Oct 19, 2023
6b4f154
Tree states release v4.5.333-exp
michaelsproul Oct 19, 2023
1aca484
Tree states release v4.5.444-exp
michaelsproul Oct 20, 2023
d36ebba
Handle out-of-order forks in epoch cache (#4881)
michaelsproul Oct 26, 2023
9cdc4b9
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Nov 12, 2023
e880d9d
Fix cache initialization in block rewards API (#4960)
michaelsproul Dec 1, 2023
66d30bc
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Dec 1, 2023
cefe9fd
Restore crash safety for database pruning (#4975)
michaelsproul Dec 4, 2023
4741bf1
Remove stray println
michaelsproul Dec 4, 2023
c8dc082
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Dec 13, 2023
8db17da
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Jan 11, 2024
664a778
Add cache for parallel HTTP requests (#4879)
michaelsproul Jan 11, 2024
9cd9243
Tree states release v4.6.111-exp
michaelsproul Jan 11, 2024
6262be7
Don't error on inactive indices in att. rewards
michaelsproul Jan 13, 2024
262e5f2
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Jan 25, 2024
11461d8
Fix new CLI tests for tree-states (#5132)
michaelsproul Jan 29, 2024
7862c71
Fix tree-states sub-epoch diffs (#5097)
michaelsproul Jan 30, 2024
8e68926
`fsync` during backfill to prevent DB corruption (#5144)
michaelsproul Jan 30, 2024
68a9a2e
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Jan 30, 2024
25bcd2a
Tree states v4.6.222-exp (#5147)
michaelsproul Jan 30, 2024
ae6620e
Delete `lighthouse db diff` (#5171)
michaelsproul Feb 2, 2024
8e2f7c5
Delete unused epoch processing code (#5170)
michaelsproul Feb 7, 2024
9eb1685
Use epoch cache in block packing (#5223)
michaelsproul Feb 14, 2024
b1f7f0a
Remove progressive balances mode (#5224)
michaelsproul Feb 14, 2024
26117a5
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Feb 22, 2024
f9c9c40
Fix tree-states tests (#5277)
michaelsproul Feb 22, 2024
20f53e7
Tree states release v5.0.111-exp (#5276)
michaelsproul Feb 23, 2024
a5d3408
Merge remote-tracking branch 'sigp/epoch-single-pass' into tree-states
dapplion Feb 23, 2024
5dfc5c1
Remove milhouse export aliases (#5286)
dapplion Feb 27, 2024
928915c
as_store_bytes not fallible (#5285)
dapplion Feb 27, 2024
a249dbf
Merge remote-tracking branch 'origin/unstable' into tree-states-update
michaelsproul Mar 11, 2024
03e2a39
Tree states release v5.1.111-exp
michaelsproul Mar 11, 2024
a9f4457
Fix macOS build by bumping `cc` (#5392)
michaelsproul Mar 12, 2024
2cd0e60
Tree states release v5.1.222-exp
michaelsproul Mar 12, 2024
0d9fb5a
Merge remote-tracking branch 'origin/unstable' into tree-states
michaelsproul Apr 5, 2024
8705ac5
Fix tree-states tests after latest update (#5528)
michaelsproul Apr 7, 2024
b5f2761
Resolve rebase_on issues
michaelsproul Apr 8, 2024
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
387 changes: 310 additions & 77 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ members = [
"common/malloc_utils",
"common/oneshot_broadcast",
"common/pretty_reqwest_error",
"common/promise_cache",
"common/sensitive_url",
"common/slot_clock",
"common/system_health",
Expand Down Expand Up @@ -102,6 +103,7 @@ bytes = "1"
clap = "2"
compare_fields_derive = { path = "common/compare_fields_derive" }
criterion = "0.3"
crossbeam-channel = "0.5.8"
delay_map = "0.3"
derivative = "2"
dirs = "3"
Expand All @@ -127,6 +129,7 @@ libsecp256k1 = "0.7"
log = "0.4"
lru = "0.12"
maplit = "1"
milhouse = { git = "https://github.com/sigp/milhouse", branch = "main" }
num_cpus = "1"
parking_lot = "0.12"
paste = "1"
Expand All @@ -153,7 +156,7 @@ smallvec = "1.11.2"
snap = "1"
ssz_types = "0.5"
strum = { version = "0.24", features = ["derive"] }
superstruct = "0.6"
superstruct = "0.7"
syn = "1"
sysinfo = "0.26"
tempfile = "3"
Expand All @@ -170,8 +173,10 @@ url = "2"
uuid = { version = "0.8", features = ["serde", "v4"] }
# TODO update to warp 0.3.6 after released.
warp = { git = "https://github.com/seanmonstar/warp.git", default-features = false, features = ["tls"] }
xdelta3 = { git = "http://github.com/michaelsproul/xdelta3-rs", rev="ae9a1d2585ef998f4656acdc35cf263ee88e6dfa" }
zeroize = { version = "1", features = ["zeroize_derive"] }
zip = "0.6"
zstd = "0.11.2"

# Local crates.
account_utils = { path = "common/account_utils" }
Expand Down
8 changes: 4 additions & 4 deletions account_manager/src/validator/exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ async fn publish_voluntary_exit<E: EthSpec>(
let validator_data = get_validator_data(client, &keypair.pk).await?;
match validator_data.status {
ValidatorStatus::ActiveExiting => {
let exit_epoch = validator_data.validator.exit_epoch;
let withdrawal_epoch = validator_data.validator.withdrawable_epoch;
let exit_epoch = validator_data.validator.exit_epoch();
let withdrawal_epoch = validator_data.validator.withdrawable_epoch();
let current_epoch = get_current_epoch::<E>(genesis_data.genesis_time, spec)
.ok_or("Failed to get current epoch. Please check your system time")?;
eprintln!("Voluntary exit has been accepted into the beacon chain, but not yet finalized. \
Expand All @@ -224,7 +224,7 @@ async fn publish_voluntary_exit<E: EthSpec>(
ValidatorStatus::ExitedSlashed | ValidatorStatus::ExitedUnslashed => {
eprintln!(
"Validator has exited on epoch: {}",
validator_data.validator.exit_epoch
validator_data.validator.exit_epoch()
);
break;
}
Expand All @@ -250,7 +250,7 @@ async fn get_validator_index_for_exit(
ValidatorStatus::ActiveOngoing => {
let eligible_epoch = validator_data
.validator
.activation_epoch
.activation_epoch()
.safe_add(spec.shard_committee_period)
.map_err(|e| format!("Failed to calculate eligible epoch, validator activation epoch too high: {:?}", e))?;

Expand Down
2 changes: 1 addition & 1 deletion beacon_node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "beacon_node"
version = "4.6.0"
version = "4.6.222-exp"
authors = [
"Paul Hauner <paul@paulhauner.com>",
"Age Manning <Age@AgeManning.com",
Expand Down
81 changes: 41 additions & 40 deletions beacon_node/beacon_chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,59 +18,60 @@ environment = { workspace = true }
serde_json = { workspace = true }

[dependencies]
serde_json = { workspace = true }
bitvec = { workspace = true }
bls = { workspace = true }
crossbeam-channel = { workspace = true }
derivative = { workspace = true }
eth1 = { workspace = true }
eth2 = { workspace = true }
eth2_network_config = { workspace = true }
merkle_proof = { workspace = true }
store = { workspace = true }
parking_lot = { workspace = true }
ethereum_hashing = { workspace = true }
ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true }
ethereum_ssz_derive = { workspace = true }
execution_layer = { workspace = true }
exit-future = { workspace = true }
fork_choice = { workspace = true }
futures = { workspace = true }
genesis = { workspace = true }
hex = { workspace = true }
int_to_bytes = { workspace = true }
itertools = { workspace = true }
kzg = { workspace = true }
lazy_static = { workspace = true }
smallvec = { workspace = true }
lighthouse_metrics = { workspace = true }
logging = { workspace = true }
lru = { workspace = true }
merkle_proof = { workspace = true }
operation_pool = { workspace = true }
parking_lot = { workspace = true }
promise_cache = { path = "../../common/promise_cache" }
proto_array = { workspace = true }
rand = { workspace = true }
rayon = { workspace = true }
safe_arith = { workspace = true }
sensitive_url = { workspace = true }
serde = { workspace = true }
ethereum_serde_utils = { workspace = true }
serde_json = { workspace = true }
slasher = { workspace = true }
slog = { workspace = true }
slog-async = { workspace = true }
slog-term = { workspace = true }
sloggers = { workspace = true }
slot_clock = { workspace = true }
ethereum_hashing = { workspace = true }
ethereum_ssz = { workspace = true }
smallvec = { workspace = true }
ssz_types = { workspace = true }
ethereum_ssz_derive = { workspace = true }
state_processing = { workspace = true }
tree_hash_derive = { workspace = true }
tree_hash = { workspace = true }
types = { workspace = true }
tokio = { workspace = true }
tokio-stream = { workspace = true }
eth1 = { workspace = true }
futures = { workspace = true }
genesis = { workspace = true }
int_to_bytes = { workspace = true }
rand = { workspace = true }
proto_array = { workspace = true }
lru = { workspace = true }
tempfile = { workspace = true }
bitvec = { workspace = true }
bls = { workspace = true }
kzg = { workspace = true }
safe_arith = { workspace = true }
fork_choice = { workspace = true }
task_executor = { workspace = true }
derivative = { workspace = true }
itertools = { workspace = true }
slasher = { workspace = true }
eth2 = { workspace = true }
store = { workspace = true }
strum = { workspace = true }
logging = { workspace = true }
execution_layer = { workspace = true }
sensitive_url = { workspace = true }
superstruct = { workspace = true }
hex = { workspace = true }
exit-future = { workspace = true }
oneshot_broadcast = { path = "../../common/oneshot_broadcast/" }
slog-term = { workspace = true }
slog-async = { workspace = true }
task_executor = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true }
tokio-stream = { workspace = true }
tree_hash = { workspace = true }
tree_hash_derive = { workspace = true }
types = { workspace = true }

[[test]]
name = "beacon_chain_tests"
Expand Down
55 changes: 34 additions & 21 deletions beacon_node/beacon_chain/src/attestation_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use safe_arith::SafeArith;
use serde_utils::quoted_u64::Quoted;
use slog::debug;
use state_processing::per_epoch_processing::altair::{
process_inactivity_updates, process_justification_and_finalization,
process_inactivity_updates_slow, process_justification_and_finalization,
};
use state_processing::{
common::altair::BaseRewardPerIncrement,
Expand Down Expand Up @@ -134,10 +134,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
let spec = &self.spec;

// Calculate ideal_rewards
let participation_cache = ParticipationCache::new(&state, spec)?;
process_justification_and_finalization(&state, &participation_cache)?
.apply_changes_to_state(&mut state);
process_inactivity_updates(&mut state, &participation_cache, spec)?;
let participation_cache = ParticipationCache::new(&state, spec)
.map_err(|_| BeaconChainError::AttestationRewardsError)?;
process_justification_and_finalization(&state)?.apply_changes_to_state(&mut state);
process_inactivity_updates_slow(&mut state, spec)?;

let previous_epoch = state.previous_epoch();

Expand All @@ -147,13 +147,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
let weight = get_flag_weight(flag_index)
.map_err(|_| BeaconChainError::AttestationRewardsError)?;

let unslashed_participating_indices = participation_cache
.get_unslashed_participating_indices(flag_index, previous_epoch)?;

let unslashed_participating_balance =
unslashed_participating_indices
.total_balance()
.map_err(|_| BeaconChainError::AttestationRewardsError)?;
let unslashed_participating_balance = participation_cache
.previous_epoch_flag_attesting_balance(flag_index)
.map_err(|_| BeaconChainError::AttestationRewardsError)?;

let unslashed_participating_increments =
unslashed_participating_balance.safe_div(spec.effective_balance_increment)?;
Expand Down Expand Up @@ -199,24 +195,41 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
Self::validators_ids_to_indices(&mut state, validators)?
};

for validator_index in &validators {
let eligible = state.is_eligible_validator(previous_epoch, *validator_index)?;
for &validator_index in &validators {
// Return 0s for unknown/inactive validator indices. This is a bit different from stable
// where we error for unknown pubkeys.
let Ok(validator) = participation_cache.get_validator(validator_index) else {
debug!(
self.log,
"No rewards for inactive/unknown validator";
"index" => validator_index,
"epoch" => previous_epoch
);
total_rewards.push(TotalAttestationRewards {
validator_index: validator_index as u64,
head: 0,
target: 0,
source: 0,
inclusion_delay: None,
inactivity: 0,
});
continue;
};
let eligible = validator.is_eligible;
let mut head_reward = 0i64;
let mut target_reward = 0i64;
let mut source_reward = 0i64;
let mut inactivity_penalty = 0i64;

if eligible {
let effective_balance = state.get_effective_balance(*validator_index)?;
let effective_balance = validator.effective_balance;

for flag_index in 0..PARTICIPATION_FLAG_WEIGHTS.len() {
let (ideal_reward, penalty) = ideal_rewards_hashmap
.get(&(flag_index, effective_balance))
.ok_or(BeaconChainError::AttestationRewardsError)?;
let voted_correctly = participation_cache
.get_unslashed_participating_indices(flag_index, previous_epoch)
.map_err(|_| BeaconChainError::AttestationRewardsError)?
.contains(*validator_index)
let voted_correctly = validator
.is_unslashed_participating_index(flag_index)
.map_err(|_| BeaconChainError::AttestationRewardsError)?;
if voted_correctly {
if flag_index == TIMELY_HEAD_FLAG_INDEX {
Expand All @@ -232,7 +245,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
target_reward = *penalty;

let penalty_numerator = effective_balance
.safe_mul(state.get_inactivity_score(*validator_index)?)?;
.safe_mul(state.get_inactivity_score(validator_index)?)?;
let penalty_denominator = spec
.inactivity_score_bias
.safe_mul(spec.inactivity_penalty_quotient_for_state(&state))?;
Expand All @@ -244,7 +257,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
}
total_rewards.push(TotalAttestationRewards {
validator_index: *validator_index as u64,
validator_index: validator_index as u64,
head: head_reward,
target: target_reward,
source: source_reward,
Expand Down
25 changes: 7 additions & 18 deletions beacon_node/beacon_chain/src/beacon_block_reward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ use operation_pool::RewardCache;
use safe_arith::SafeArith;
use slog::error;
use state_processing::{
common::{
altair, get_attestation_participation_flag_indices, get_attesting_indices_from_state,
},
common::{get_attestation_participation_flag_indices, get_attesting_indices_from_state},
epoch_cache::initialize_epoch_cache,
per_block_processing::{
altair::sync_committee::compute_sync_aggregate_rewards, get_slashable_indices,
},
Expand All @@ -32,6 +31,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {

state.build_committee_cache(RelativeEpoch::Previous, &self.spec)?;
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
initialize_epoch_cache(state, &self.spec)?;

self.compute_beacon_block_reward_with_cache(block, block_root, state)
}
Expand Down Expand Up @@ -135,7 +135,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
proposer_slashing_reward.safe_add_assign(
state
.get_validator(proposer_slashing.proposer_index() as usize)?
.effective_balance
.effective_balance()
.safe_div(self.spec.whistleblower_reward_quotient)?,
)?;
}
Expand All @@ -157,7 +157,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
attester_slashing_reward.safe_add_assign(
state
.get_validator(attester_index as usize)?
.effective_balance
.effective_balance()
.safe_div(self.spec.whistleblower_reward_quotient)?,
)?;
}
Expand Down Expand Up @@ -191,10 +191,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
state: &BeaconState<T::EthSpec>,
) -> Result<BeaconBlockSubRewardValue, BeaconChainError> {
let total_active_balance = state.get_total_active_balance()?;
let base_reward_per_increment =
altair::BaseRewardPerIncrement::new(total_active_balance, &self.spec)?;

let mut total_proposer_reward = 0;

let proposer_reward_denominator = WEIGHT_DENOMINATOR
Expand Down Expand Up @@ -235,15 +231,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
&& !validator_participation.has_flag(flag_index)?
{
validator_participation.add_flag(flag_index)?;
proposer_reward_numerator.safe_add_assign(
altair::get_base_reward(
state,
index,
base_reward_per_increment,
&self.spec,
)?
.safe_mul(weight)?,
)?;
proposer_reward_numerator
.safe_add_assign(state.get_base_reward(index)?.safe_mul(weight)?)?;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/src/beacon_block_streamer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl<T: BeaconChainTypes> BeaconBlockStreamer<T> {
continue;
}

match self.beacon_chain.store.try_get_full_block(&root) {
match self.beacon_chain.store.try_get_full_block(&root, None) {
Err(e) => db_blocks.push((root, Err(e.into()))),
Ok(opt_block) => db_blocks.push((
root,
Expand Down
Loading