Skip to content

Commit b02dfab

Browse files
authored
Merge branch 'main' into refactor/use-genserver-instead-sync-threads
2 parents 762ebf8 + 1c4851c commit b02dfab

File tree

5 files changed

+48
-8
lines changed

5 files changed

+48
-8
lines changed

.github/workflows/pr-main_l1.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ jobs:
176176
runs-on: ubuntu-latest
177177
needs: [detect-changes, docker_build]
178178
if: ${{ needs.detect-changes.outputs.run_tests == 'true' && github.event_name != 'merge_group' }}
179+
env:
180+
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
179181
strategy:
180182
fail-fast: false
181183
matrix:
@@ -252,10 +254,11 @@ jobs:
252254
echo "flags=$FLAGS" >> "$GITHUB_OUTPUT"
253255
254256
- name: Log in to the Container registry
257+
if: ${{ env.DOCKERHUB_TOKEN != '' }}
255258
uses: docker/login-action@v3
256259
with:
257260
username: ${{ vars.DOCKERHUB_USERNAME }}
258-
password: ${{ secrets.DOCKERHUB_TOKEN }}
261+
password: ${{ env.DOCKERHUB_TOKEN }}
259262

260263
- name: Run Hive Simulation
261264
id: run-hive-action

crates/blockchain/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,8 @@ pub enum InvalidForkChoice {
175175
InvalidAncestor(BlockHash),
176176
#[error("Cannot find link between Head and the canonical chain")]
177177
UnlinkedHead,
178+
179+
// TODO(#5564): handle arbitrary reorgs
180+
#[error("State root of the new head is not reachable from the database")]
181+
StateNotReachable,
178182
}

crates/blockchain/fork_choice.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use ethrex_common::{
44
};
55
use ethrex_metrics::metrics;
66
use ethrex_storage::{Store, error::StoreError};
7+
use tracing::{error, warn};
78

89
use crate::{
910
error::{self, InvalidForkChoice},
@@ -67,9 +68,9 @@ pub async fn apply_fork_choice(
6768
return Err(InvalidForkChoice::UnlinkedHead);
6869
};
6970

70-
let link_block_number = match new_canonical_blocks.last() {
71-
Some((number, _)) => *number,
72-
None => head.number,
71+
let (link_block_number, link_block_hash) = match new_canonical_blocks.last() {
72+
Some((number, hash)) => (*number, *hash),
73+
None => (head.number, head_hash),
7374
};
7475

7576
// Check that finalized and safe blocks are part of the new canonical chain.
@@ -97,6 +98,24 @@ pub async fn apply_fork_choice(
9798
));
9899
}
99100

101+
let Some(link_header) = store.get_block_header_by_hash(link_block_hash)? else {
102+
// Probably unreachable, but we return this error just in case.
103+
error!("Link block not found although it was just retrieved from the DB");
104+
return Err(InvalidForkChoice::UnlinkedHead);
105+
};
106+
107+
// If the state can't be constructed from the DB, we ignore it and log a warning.
108+
// TODO(#5564): handle arbitrary reorgs
109+
if !store.has_state_root(link_header.state_root)? {
110+
warn!(
111+
link_block=%link_block_hash,
112+
link_number=%link_header.number,
113+
head_number=%head.number,
114+
"FCU head state not reachable from DB state. Ignoring fork choice update. This is expected if the consensus client is currently syncing. Otherwise, if consensus is synced and this is a consistent message it can be fixed by removing the DB and re-syncing the execution client."
115+
);
116+
return Err(InvalidForkChoice::StateNotReachable);
117+
}
118+
100119
// Finished all validations.
101120

102121
store

crates/networking/p2p/discv4/server.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ impl DiscoveryServer {
182182
return Ok(());
183183
}
184184

185-
self.handle_find_node(sender_public_key, from).await?;
185+
self.handle_find_node(sender_public_key, find_node_message.target, from)
186+
.await?;
186187
}
187188
Message::Neighbors(neighbors_message) => {
188189
trace!(received = "Neighbors", msg = ?neighbors_message, from = %format!("{sender_public_key:#x}"));
@@ -425,14 +426,18 @@ impl DiscoveryServer {
425426
async fn handle_find_node(
426427
&mut self,
427428
sender_public_key: H512,
429+
target: H512,
428430
from: SocketAddr,
429431
) -> Result<(), DiscoveryServerError> {
430-
let node_id = node_id(&sender_public_key);
432+
let sender_id = node_id(&sender_public_key);
431433
if let Ok(contact) = self
432-
.validate_contact(sender_public_key, node_id, from, "FindNode")
434+
.validate_contact(sender_public_key, sender_id, from, "FindNode")
433435
.await
434436
{
435-
let neighbors = self.peer_table.get_closest_nodes(&node_id).await?;
437+
// According to https://github.com/ethereum/devp2p/blob/master/discv4.md#findnode-packet-0x03
438+
// reply closest 16 nodes to target
439+
let target_id = node_id(&target);
440+
let neighbors = self.peer_table.get_closest_nodes(&target_id).await?;
436441

437442
// A single node encodes to at most 89B, so 8 of them are at most 712B plus
438443
// recursive length and expiration time, well within bound of 1280B per packet.

crates/networking/rpc/engine/fork_choice.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ async fn handle_forkchoice(
220220
));
221221
}
222222

223+
// Ignore any FCU during snap-sync.
224+
// Processing the FCU while snap-syncing can result in reading inconsistent data
225+
// from the DB, and the later head update can overwrite changes made by the syncer
226+
// process, corrupting the forkchoice state (see #5547)
223227
if syncer.sync_mode() == SyncMode::Snap {
224228
syncer.sync_to_head(fork_choice_state.head_block_hash);
225229
return Ok((None, PayloadStatus::syncing().into()));
@@ -275,6 +279,11 @@ async fn handle_forkchoice(
275279
syncer.sync_to_head(fork_choice_state.head_block_hash);
276280
ForkChoiceResponse::from(PayloadStatus::syncing())
277281
}
282+
// TODO(#5564): handle arbitrary reorgs
283+
InvalidForkChoice::StateNotReachable => {
284+
// Ignore the FCU
285+
ForkChoiceResponse::from(PayloadStatus::syncing())
286+
}
278287
InvalidForkChoice::Disconnected(_, _) | InvalidForkChoice::ElementNotFound(_) => {
279288
warn!("Invalid fork choice state. Reason: {:?}", forkchoice_error);
280289
return Err(RpcErr::InvalidForkChoiceState(forkchoice_error.to_string()));

0 commit comments

Comments
 (0)