mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
fix(engine): only warn for critical capability mismatches (#21398)
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -3,6 +3,13 @@
|
||||
use std::collections::HashSet;
|
||||
use tracing::warn;
|
||||
|
||||
/// Critical Engine API method prefixes that warrant warnings on capability mismatches.
|
||||
///
|
||||
/// These are essential for block production and chain synchronization. Missing support
|
||||
/// for these methods indicates a significant version mismatch that operators should address.
|
||||
const CRITICAL_METHOD_PREFIXES: &[&str] =
|
||||
&["engine_forkchoiceUpdated", "engine_getPayload", "engine_newPayload"];
|
||||
|
||||
/// All Engine API capabilities supported by Reth (Ethereum mainnet).
|
||||
///
|
||||
/// See <https://github.com/ethereum/execution-apis/tree/main/src/engine> for updates.
|
||||
@@ -72,31 +79,52 @@ impl EngineCapabilities {
|
||||
CapabilityMismatches { missing_in_el, missing_in_cl }
|
||||
}
|
||||
|
||||
/// Logs warnings if CL and EL capabilities don't match.
|
||||
/// Logs warnings if CL and EL capabilities don't match for critical methods.
|
||||
///
|
||||
/// Called during `engine_exchangeCapabilities` to warn operators about
|
||||
/// version mismatches between the consensus layer and execution layer.
|
||||
///
|
||||
/// Only warns about critical methods (`engine_forkchoiceUpdated`, `engine_getPayload`,
|
||||
/// `engine_newPayload`) that are essential for block production and chain synchronization.
|
||||
/// Non-critical methods like `engine_getBlobs` are not warned about since not all
|
||||
/// clients support them.
|
||||
pub fn log_capability_mismatches(&self, cl_capabilities: &[String]) {
|
||||
let mismatches = self.get_capability_mismatches(cl_capabilities);
|
||||
|
||||
if !mismatches.missing_in_el.is_empty() {
|
||||
let critical_missing_in_el: Vec<_> =
|
||||
mismatches.missing_in_el.iter().filter(|m| is_critical_method(m)).cloned().collect();
|
||||
|
||||
let critical_missing_in_cl: Vec<_> =
|
||||
mismatches.missing_in_cl.iter().filter(|m| is_critical_method(m)).cloned().collect();
|
||||
|
||||
if !critical_missing_in_el.is_empty() {
|
||||
warn!(
|
||||
target: "rpc::engine",
|
||||
missing = ?mismatches.missing_in_el,
|
||||
missing = ?critical_missing_in_el,
|
||||
"CL supports Engine API methods that Reth doesn't. Consider upgrading Reth."
|
||||
);
|
||||
}
|
||||
|
||||
if !mismatches.missing_in_cl.is_empty() {
|
||||
if !critical_missing_in_cl.is_empty() {
|
||||
warn!(
|
||||
target: "rpc::engine",
|
||||
missing = ?mismatches.missing_in_cl,
|
||||
missing = ?critical_missing_in_cl,
|
||||
"Reth supports Engine API methods that CL doesn't. Consider upgrading your consensus client."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the method is critical for block production and chain synchronization.
|
||||
fn is_critical_method(method: &str) -> bool {
|
||||
CRITICAL_METHOD_PREFIXES.iter().any(|prefix| {
|
||||
method.starts_with(prefix) &&
|
||||
method[prefix.len()..]
|
||||
.strip_prefix('V')
|
||||
.is_some_and(|s| s.chars().next().is_some_and(|c| c.is_ascii_digit()))
|
||||
})
|
||||
}
|
||||
|
||||
impl Default for EngineCapabilities {
|
||||
fn default() -> Self {
|
||||
Self::new(CAPABILITIES.iter().copied())
|
||||
@@ -173,4 +201,20 @@ mod tests {
|
||||
assert_eq!(result.missing_in_el, vec!["a_other", "z_other"]);
|
||||
assert_eq!(result.missing_in_cl, vec!["a_method", "z_method"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_critical_method() {
|
||||
assert!(is_critical_method("engine_forkchoiceUpdatedV1"));
|
||||
assert!(is_critical_method("engine_forkchoiceUpdatedV3"));
|
||||
assert!(is_critical_method("engine_getPayloadV1"));
|
||||
assert!(is_critical_method("engine_getPayloadV4"));
|
||||
assert!(is_critical_method("engine_newPayloadV1"));
|
||||
assert!(is_critical_method("engine_newPayloadV4"));
|
||||
|
||||
assert!(!is_critical_method("engine_getBlobsV1"));
|
||||
assert!(!is_critical_method("engine_getBlobsV3"));
|
||||
assert!(!is_critical_method("engine_getPayloadBodiesByHashV1"));
|
||||
assert!(!is_critical_method("engine_getPayloadBodiesByRangeV1"));
|
||||
assert!(!is_critical_method("engine_getClientVersionV1"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user