diff --git a/engine/src/dot/http_rpc.rs b/engine/src/dot/http_rpc.rs index 16a2e3ca00..497549c1ea 100644 --- a/engine/src/dot/http_rpc.rs +++ b/engine/src/dot/http_rpc.rs @@ -21,6 +21,7 @@ use subxt::{ }; use anyhow::Result; +use tracing::{error, warn}; use utilities::{make_periodic_tick, redact_endpoint_secret::SecretUrl}; use crate::constants::RPC_RETRY_CONNECTION_INTERVAL; @@ -82,7 +83,7 @@ pub struct DotHttpRpcClient { impl DotHttpRpcClient { pub fn new( url: SecretUrl, - expected_genesis_hash: PolkadotHash, + expected_genesis_hash: Option, ) -> Result> { let polkadot_http_client = Arc::new(PolkadotHttpClient::new(&url)?); @@ -98,17 +99,22 @@ impl DotHttpRpcClient { .await { Ok(online_client) => { - let genesis_hash = online_client.genesis_hash(); - if genesis_hash == expected_genesis_hash { - break online_client + if let Some(expected_genesis_hash) = expected_genesis_hash { + let genesis_hash = online_client.genesis_hash(); + if genesis_hash == expected_genesis_hash { + break online_client + } else { + error!( + "Connected to Polkadot node at {url} but the genesis hash {genesis_hash} does not match the expected genesis hash {expected_genesis_hash}. Please check your CFE configuration file." + ) + } } else { - tracing::error!( - "Connected to Polkadot node at {url} but the genesis hash {genesis_hash} does not match the expected genesis hash {expected_genesis_hash}. Please check your CFE configuration file." - ) + warn!("Skipping Polkadot genesis hash check"); + break online_client } }, Err(e) => { - tracing::error!( + error!( "Failed to connect to Polkadot node at {url} with error: {e}. Please check your CFE configuration file. Retrying in {:?}...", poll_interval.period() @@ -213,11 +219,8 @@ mod tests { #[ignore = "requires local node"] #[tokio::test] async fn test_http_rpc() { - // This will no longer work because we need to know the genesis hash let dot_http_rpc = - DotHttpRpcClient::new("http://localhost:9945".into(), PolkadotHash::default()) - .unwrap() - .await; + DotHttpRpcClient::new("http://localhost:9945".into(), None).unwrap().await; let block_hash = dot_http_rpc.block_hash(1).await.unwrap(); println!("block_hash: {:?}", block_hash); } diff --git a/engine/src/dot/retry_rpc.rs b/engine/src/dot/retry_rpc.rs index 913c3acc89..6b705efd53 100644 --- a/engine/src/dot/retry_rpc.rs +++ b/engine/src/dot/retry_rpc.rs @@ -45,6 +45,15 @@ impl DotRetryRpcClient { scope: &Scope<'_, anyhow::Error>, nodes: NodeContainer, expected_genesis_hash: PolkadotHash, + ) -> Result { + Self::new_ext(scope, nodes, Some(expected_genesis_hash)) + } + + fn new_ext( + scope: &Scope<'_, anyhow::Error>, + nodes: NodeContainer, + // The genesis hash is optional to facilitate testing + expected_genesis_hash: Option, ) -> Result { let f_create_clients = |endpoints: WsHttpEndpoints| { Result::<_, anyhow::Error>::Ok(( @@ -58,7 +67,7 @@ impl DotRetryRpcClient { let (backup_rpc_client, backup_sub_client) = option_inner(nodes.backup.map(f_create_clients).transpose()?); - Ok(Self { + Ok(DotRetryRpcClient { rpc_retry_client: RetrierClient::new( scope, "dot_rpc", @@ -307,8 +316,7 @@ mod tests { async fn my_test() { task_scope(|scope| { async move { - // This will no longer work because we need to know the genesis hash - let dot_retry_rpc_client = DotRetryRpcClient::new( + let dot_retry_rpc_client = DotRetryRpcClient::new_ext( scope, NodeContainer { primary: WsHttpEndpoints { @@ -317,7 +325,7 @@ mod tests { }, backup: None, }, - PolkadotHash::default(), + None, ) .unwrap(); diff --git a/engine/src/dot/rpc.rs b/engine/src/dot/rpc.rs index 81ce4f1541..e36884b5f3 100644 --- a/engine/src/dot/rpc.rs +++ b/engine/src/dot/rpc.rs @@ -12,6 +12,7 @@ use subxt::{ Config, OnlineClient, PolkadotConfig, }; use tokio::sync::RwLock; +use tracing::warn; use utilities::redact_endpoint_secret::SecretUrl; use anyhow::{anyhow, bail, Result}; @@ -136,11 +137,11 @@ impl DotRpcApi for DotRpcClient { #[derive(Clone)] pub struct DotSubClient { pub ws_endpoint: SecretUrl, - expected_genesis_hash: PolkadotHash, + expected_genesis_hash: Option, } impl DotSubClient { - pub fn new(ws_endpoint: SecretUrl, expected_genesis_hash: PolkadotHash) -> Self { + pub fn new(ws_endpoint: SecretUrl, expected_genesis_hash: Option) -> Self { Self { ws_endpoint, expected_genesis_hash } } } @@ -150,12 +151,7 @@ impl DotSubscribeApi for DotSubClient { async fn subscribe_best_heads( &self, ) -> Result> + Send>>> { - let client = OnlineClient::::from_url(&self.ws_endpoint).await?; - - let genesis_hash = client.genesis_hash(); - if genesis_hash != self.expected_genesis_hash { - bail!("Expected genesis hash {} but got {genesis_hash}", self.expected_genesis_hash); - } + let client = create_online_client(&self.ws_endpoint, self.expected_genesis_hash).await?; Ok(Box::pin( client @@ -170,12 +166,7 @@ impl DotSubscribeApi for DotSubClient { async fn subscribe_finalized_heads( &self, ) -> Result> + Send>>> { - let client = OnlineClient::::from_url(&self.ws_endpoint).await?; - - let genesis_hash = client.genesis_hash(); - if genesis_hash != self.expected_genesis_hash { - bail!("Expected genesis hash {} but got {genesis_hash}", self.expected_genesis_hash); - } + let client = create_online_client(&self.ws_endpoint, self.expected_genesis_hash).await?; Ok(Box::pin( client @@ -188,6 +179,26 @@ impl DotSubscribeApi for DotSubClient { } } +/// Creates an OnlineClient from the given websocket endpoint and checks the genesis hash if +/// provided. +async fn create_online_client( + ws_endpoint: &SecretUrl, + expected_genesis_hash: Option, +) -> Result> { + let client = OnlineClient::::from_url(ws_endpoint).await?; + + if let Some(expected_genesis_hash) = expected_genesis_hash { + let genesis_hash = client.genesis_hash(); + if genesis_hash != expected_genesis_hash { + bail!("Expected Polkadot genesis hash {expected_genesis_hash} but got {genesis_hash}"); + } + } else { + warn!("Skipping Polkadot genesis hash check"); + } + + Ok(client) +} + #[async_trait] impl DotSubscribeApi for DotRpcClient { async fn subscribe_best_heads(