Skip to content

Commit 521a9b6

Browse files
authored
fix(l1): fcu not triggering sync if snap is enabled + re-enable snap sync hive test (#2605)
**Motivation** PR #2426 changed how fork choice & new payload interact with the syncer and also introduced a bug. If snap sync is enabled, then fork choice update will never attempt to trigger a sync, so the sync process never gets started. This PR fixes the bug and also refactors the sync manager api to better suit the new use cases <!-- Why does this pull request exist? What are its goals? --> * Combine commonly used together `SyncManager` methods `set_head` & `start_sync` into `sync_to_head` * Remove unused `SyncManager` method `status` and associated struct * Make sure sync is triggered during fcu when needed even if snap sync is enabled * Re-enable snap sync hive test suite **Description** <!-- A clear and concise general description of the changes this PR introduces --> <!-- Link to issues: Resolves #111, Resolves #222 --> Closes #2521
1 parent 7902f16 commit 521a9b6

File tree

4 files changed

+35
-37
lines changed

4 files changed

+35
-37
lines changed

.github/workflows/pr-main_l1.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,10 @@ jobs:
169169
simulation: ethereum/sync
170170
test_pattern: ""
171171
ethrex_flags: "--syncmode full"
172-
# Flaky test, reenable when fixed
173-
# - name: "Sync snap"
174-
# simulation: ethereum/sync
175-
# test_pattern: ""
176-
# ethrex_flags: "--syncmode snap"
172+
- name: "Sync snap"
173+
simulation: ethereum/sync
174+
test_pattern: ""
175+
ethrex_flags: "--syncmode snap"
177176
steps:
178177
- name: Checkout sources
179178
uses: actions/checkout@v4

crates/networking/p2p/sync_manager.rs

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::sync::{
55

66
use ethrex_blockchain::Blockchain;
77
use ethrex_common::H256;
8-
use ethrex_storage::{error::StoreError, Store};
8+
use ethrex_storage::Store;
99
use tokio::{
1010
sync::Mutex,
1111
time::{sleep, Duration},
@@ -18,12 +18,6 @@ use crate::{
1818
sync::{SyncMode, Syncer},
1919
};
2020

21-
#[derive(Debug)]
22-
pub enum SyncStatus {
23-
Active(SyncMode),
24-
Inactive,
25-
}
26-
2721
/// Abstraction to interact with the active sync process without disturbing it
2822
#[derive(Debug)]
2923
pub struct SyncManager {
@@ -80,35 +74,48 @@ impl SyncManager {
8074
}
8175
}
8276

77+
/// Sets the latest fcu head and starts the next sync cycle if the syncer is currently inactive
78+
pub fn sync_to_head(&self, fcu_head: H256) {
79+
self.set_head(fcu_head);
80+
if !self.is_active() {
81+
self.start_sync();
82+
}
83+
}
84+
85+
/// Returns the syncer's current syncmode (either snap or full)
86+
pub fn sync_mode(&self) -> SyncMode {
87+
if self.snap_enabled.load(Ordering::Relaxed) {
88+
SyncMode::Snap
89+
} else {
90+
SyncMode::Full
91+
}
92+
}
93+
8394
/// Updates the last fcu head. This may be used on the next sync cycle if needed
84-
pub fn set_head(&self, fcu_head: H256) {
95+
fn set_head(&self, fcu_head: H256) {
8596
if let Ok(mut latest_fcu_head) = self.last_fcu_head.try_lock() {
8697
*latest_fcu_head = fcu_head;
8798
} else {
8899
warn!("Failed to update latest fcu head for syncing")
89100
}
90101
}
91102

92-
/// Returns the current sync status, either active or inactive and what the current syncmode is in the case of active
93-
pub fn status(&self) -> Result<SyncStatus, StoreError> {
94-
Ok(if self.syncer.try_lock().is_err() {
95-
SyncStatus::Active(self.sync_mode())
96-
} else {
97-
SyncStatus::Inactive
98-
})
103+
/// Returns true is the syncer is active
104+
fn is_active(&self) -> bool {
105+
self.syncer.try_lock().is_err()
99106
}
100107

101108
/// Attempts to sync to the last received fcu head
102109
/// Will do nothing if the syncer is already involved in a sync process
103110
/// If the sync process would require multiple sync cycles (such as snap sync), starts all required sync cycles until the sync is complete
104-
pub fn start_sync(&self) {
111+
fn start_sync(&self) {
105112
let syncer = self.syncer.clone();
106113
let store = self.store.clone();
107114
let sync_head = self.last_fcu_head.clone();
108115

109116
tokio::spawn(async move {
110117
let Ok(Some(current_head)) = store.get_latest_canonical_block_hash().await else {
111-
tracing::error!("Failed to fecth latest canonical block, unable to sync");
118+
tracing::error!("Failed to fetch latest canonical block, unable to sync");
112119
return;
113120
};
114121

@@ -148,13 +155,4 @@ impl SyncManager {
148155
}
149156
});
150157
}
151-
152-
/// Returns the syncer's current syncmode (either snap or full)
153-
pub fn sync_mode(&self) -> SyncMode {
154-
if self.snap_enabled.load(Ordering::Relaxed) {
155-
SyncMode::Snap
156-
} else {
157-
SyncMode::Full
158-
}
159-
}
160158
}

crates/networking/rpc/engine/fork_choice.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,9 @@ async fn handle_forkchoice(
250250
}
251251

252252
if context.syncer.sync_mode() == SyncMode::Snap {
253-
context.syncer.set_head(fork_choice_state.head_block_hash);
253+
context
254+
.syncer
255+
.sync_to_head(fork_choice_state.head_block_hash);
254256
return Ok((None, PayloadStatus::syncing().into()));
255257
}
256258

@@ -312,8 +314,9 @@ async fn handle_forkchoice(
312314
.update_sync_status(false)
313315
.await
314316
.map_err(|e| RpcErr::Internal(e.to_string()))?;
315-
context.syncer.set_head(fork_choice_state.head_block_hash);
316-
context.syncer.start_sync();
317+
context
318+
.syncer
319+
.sync_to_head(fork_choice_state.head_block_hash);
317320
ForkChoiceResponse::from(PayloadStatus::syncing())
318321
}
319322
InvalidForkChoice::Disconnected(_, _) | InvalidForkChoice::ElementNotFound(_) => {

crates/networking/rpc/engine/payload.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,7 @@ async fn try_execute_payload(
698698
.update_sync_status(false)
699699
.await
700700
.map_err(|e| RpcErr::Internal(e.to_string()))?;
701-
context.syncer.set_head(block_hash);
702-
context.syncer.start_sync();
703-
701+
context.syncer.sync_to_head(block_hash);
704702
Ok(PayloadStatus::syncing())
705703
}
706704
// Under the current implementation this is not possible: we always calculate the state

0 commit comments

Comments
 (0)