Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions crates/common/chain/lean/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ version.workspace = true
default = ["devnet2"]
devnet2 = [
"ream-consensus-lean/devnet2",
"ream-consensus-misc/devnet2",
"ream-fork-choice-lean/devnet2",
"ream-network-state-lean/devnet2",
]
devnet3 = [
"ream-consensus-lean/devnet3",
"ream-consensus-misc/devnet3",
"ream-fork-choice-lean/devnet3",
"ream-network-state-lean/devnet3",
]
Expand Down
68 changes: 54 additions & 14 deletions crates/common/chain/lean/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use ream_consensus_lean::{
block::{BlockWithSignatures, SignedBlockWithAttestation},
checkpoint::Checkpoint,
};
use ream_consensus_misc::constants::lean::INTERVALS_PER_SLOT;
use ream_fork_choice_lean::store::LeanStoreWriter;
use ream_metrics::{CURRENT_SLOT, set_int_gauge_vec};
use ream_network_spec::networks::lean_network_spec;
Expand Down Expand Up @@ -127,14 +128,18 @@ impl LeanChainService {

tokio::select! {
_ = interval.tick() => {
if tick_count.is_multiple_of(4) {
if tick_count.is_multiple_of(INTERVALS_PER_SLOT) {
self.sync_status = self.update_sync_status().await?;
}
if self.sync_status == SyncStatus::Synced {
#[cfg(feature = "devnet2")]
self.store.write().await.tick_interval(tick_count % 4 == 1).await.expect("Failed to tick interval");
#[cfg(feature = "devnet3")]
self.store.write().await.tick_interval(tick_count % 4 == 1, false).await.expect("Failed to tick interval");
{
// TODO: update is_aggregator logic from devnet config
let is_aggregator = true;
self.store.write().await.tick_interval(tick_count.is_multiple_of(INTERVALS_PER_SLOT), is_aggregator).await.expect("Failed to tick interval");
}
self.step_head_sync(tick_count).await?;
}

Expand Down Expand Up @@ -394,9 +399,10 @@ impl LeanChainService {
}

async fn step_head_sync(&mut self, tick_count: u64) -> anyhow::Result<()> {
match tick_count % 4 {
let interval = tick_count % INTERVALS_PER_SLOT;
match interval {
0 => {
// First tick (t=0/4): Log current head state, including its
// First tick: Log current head state, including its
// justification/finalization status.
let (head, state_provider) = {
let fork_choice = self.store.read().await;
Expand Down Expand Up @@ -435,8 +441,15 @@ impl LeanChainService {
finalized_root = head_state.latest_finalized.root,
);
}
1 => {
// Second tick: Prune old data.
if let Err(err) = self.prune_old_state(tick_count).await {
warn!("Pruning cycle failed (non-fatal): {err:?}");
}
}
#[cfg(feature = "devnet2")]
2 => {
// Third tick (t=2/4): Compute the safe target.
// Third tick (devnet2): Compute the safe target.
info!(
slot = get_current_slot(),
tick = tick_count,
Expand All @@ -449,8 +462,9 @@ impl LeanChainService {
.await
.expect("Failed to update safe target");
}
#[cfg(feature = "devnet2")]
3 => {
// Fourth tick (t=3/4): Accept new attestations.
// Fourth tick (devnet2): Accept new attestations.
info!(
slot = get_current_slot(),
tick = tick_count,
Expand All @@ -463,13 +477,39 @@ impl LeanChainService {
.await
.expect("Failed to accept new attestations");
}
1 => {
// Other ticks (t=0, t=1/4): Prune old data.
if let Err(err) = self.prune_old_state(tick_count).await {
warn!("Pruning cycle failed (non-fatal): {err:?}");
}
#[cfg(feature = "devnet3")]
3 => {
// Fourth tick (devnet3): Compute the safe target.
info!(
slot = get_current_slot(),
tick = tick_count,
"Computing safe target"
);
self.store
.write()
.await
.update_safe_target()
.await
.expect("Failed to update safe target");
}
#[cfg(feature = "devnet3")]
4 => {
// Fifth tick (devnet3): Accept new attestations.
info!(
slot = get_current_slot(),
tick = tick_count,
"Accepting new attestations"
);
self.store
.write()
.await
.accept_new_attestations()
.await
.expect("Failed to accept new attestations");
}
_ => {
// Other ticks: Do nothing.
}
_ => unreachable!("Tick count modulo 4 should be in 0..=3"),
}
Ok(())
}
Expand Down Expand Up @@ -660,7 +700,7 @@ impl LeanChainService {
#[cfg(feature = "devnet2")]
self.store.write().await.on_tick(now, false).await?;
#[cfg(feature = "devnet3")]
self.store.write().await.on_tick(now, false, false).await?;
self.store.write().await.on_tick(now, false, true).await?;
}

Ok(sync_status)
Expand Down Expand Up @@ -980,7 +1020,7 @@ impl LeanChainService {
self.store
.write()
.await
.on_gossip_attestation(signed_attestation, false)
.on_gossip_attestation(signed_attestation, true)
.await?;

Ok(())
Expand Down
4 changes: 4 additions & 0 deletions crates/common/consensus/misc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ repository.workspace = true
rust-version.workspace = true
version.workspace = true

[features]
devnet2 = []
devnet3 = []

[dependencies]
alloy-primitives.workspace = true
alloy-rlp.workspace = true
Expand Down
8 changes: 5 additions & 3 deletions crates/common/consensus/misc/src/constants/lean.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/// 3SF-mini divides a slot into 4 intervals.
/// Reference: https://github.com/ethereum/research/blob/d225a6775a9b184b5c1fd6c830cc58a375d9535f/3sf-mini/p2p.py#L77-L98
pub const ATTESTATION_COMMITTEE_COUNT: u64 = 1;

#[cfg(feature = "devnet2")]
pub const INTERVALS_PER_SLOT: u64 = 4;
#[cfg(feature = "devnet3")]
pub const INTERVALS_PER_SLOT: u64 = 5;
pub const MAX_HISTORICAL_BLOCK_HASHES: u64 = 262144;
pub const SLOT_DURATION: u64 = 12;
pub const SLOT_DURATION: u64 = 4;
pub const VALIDATOR_REGISTRY_LIMIT: u64 = 4096;
2 changes: 2 additions & 0 deletions crates/common/fork_choice/lean/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ version.workspace = true
default = ["devnet2"]
devnet2 = [
"ream-consensus-lean/devnet2",
"ream-consensus-misc/devnet2",
"ream-network-state-lean/devnet2",
"ream-storage/devnet2",
]
devnet3 = [
"ream-consensus-lean/devnet3",
"ream-consensus-misc/devnet3",
"ream-network-state-lean/devnet3",
"ream-storage/devnet3",
]
Expand Down
3 changes: 2 additions & 1 deletion crates/common/fork_choice/lean/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ impl Store {
is_aggregator: bool,
) -> anyhow::Result<()> {
let time_delta_ms = (time - lean_network_spec().genesis_time) * 1000;
let tick_interval_time = time_delta_ms / lean_network_spec().seconds_per_slot * 1000 / 5;
let tick_interval_time =
time_delta_ms * INTERVALS_PER_SLOT / (lean_network_spec().seconds_per_slot * 1000);

let time_provider = self.store.lock().await.time_provider();
while time_provider.get()? < tick_interval_time {
Expand Down
5 changes: 3 additions & 2 deletions crates/common/validator/lean/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use ream_consensus_lean::{
};
#[cfg(feature = "devnet3")]
use ream_consensus_misc::constants::lean::ATTESTATION_COMMITTEE_COUNT;
use ream_consensus_misc::constants::lean::INTERVALS_PER_SLOT;
#[cfg(feature = "devnet3")]
use ream_fork_choice_lean::store::compute_subnet_id;
use ream_keystore::lean_keystore::ValidatorKeystore;
Expand Down Expand Up @@ -65,8 +66,8 @@ impl ValidatorService {
loop {
tokio::select! {
_ = interval.tick() => {
let slot = tick_count / 4;
match tick_count % 4 {
let slot = tick_count / INTERVALS_PER_SLOT;
match tick_count % INTERVALS_PER_SLOT {
0 => {
// First tick (t=0): Propose a block.
if slot > 0 && let Some(keystore) = self.is_proposer(slot) {
Expand Down
Loading