From bc1323a811efc3f078d3d553ff960ddb9b77e847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Thu, 14 Nov 2024 14:23:06 +0100 Subject: [PATCH] validate network name when connecting RPC client --- rpc_sidecar/src/node_client.rs | 86 +++++++++++++++++++++++++++++----- rpc_sidecar/src/testing/mod.rs | 19 ++++++++ 2 files changed, 92 insertions(+), 13 deletions(-) diff --git a/rpc_sidecar/src/node_client.rs b/rpc_sidecar/src/node_client.rs index 0228438c..c3d4ce48 100644 --- a/rpc_sidecar/src/node_client.rs +++ b/rpc_sidecar/src/node_client.rs @@ -835,17 +835,29 @@ impl FramedNodeClient { Arc::clone(&reconnect), ); - Ok(( - Self { - client: Arc::clone(&stream), - request_limit: Semaphore::new(config.request_limit as usize), - reconnect, - shutdown, - config, - current_request_id: AtomicU16::new(INITIAL_REQUEST_ID), - }, - reconnect_loop, - )) + // clone network name for validation later + let maybe_network_name = config.network_name.clone(); + + let node_client = Self { + client: Arc::clone(&stream), + request_limit: Semaphore::new(config.request_limit as usize), + reconnect, + shutdown, + config, + current_request_id: AtomicU16::new(INITIAL_REQUEST_ID), + }; + + // validate network name + if let Some(network_name) = maybe_network_name { + let node_status = node_client.read_node_status().await?; + if network_name != node_status.chainspec_name { + let msg = format!("Network name {} does't match name {network_name} configured for node RPC connection", node_status.chainspec_name); + error!("{msg}"); + return Err(AnyhowError::msg(msg)); + } + } + + Ok((node_client, reconnect_loop)) } fn next_id(&self) -> u16 { @@ -1165,13 +1177,14 @@ where mod tests { use crate::testing::{ get_dummy_request, get_dummy_request_payload, get_port, start_mock_binary_port, + start_mock_binary_port_responding_with_given_response, start_mock_binary_port_responding_with_stored_value, }; use super::*; - use casper_binary_port::BinaryRequestHeader; + use casper_binary_port::{BinaryRequestHeader, ReactorStateName}; use casper_types::testing::TestRng; - use casper_types::{CLValue, SemVer}; + use casper_types::{BlockSynchronizerStatus, CLValue, SemVer, TimeDiff, Timestamp}; use futures::FutureExt; use tokio::time::sleep; @@ -1317,6 +1330,53 @@ mod tests { assert_eq!(res, StoredValue::CLValue(CLValue::from_t("Foo").unwrap())) } + #[tokio::test] + async fn should_fail_to_connect_if_network_name_does_not_match() { + // prepare node status response with network name + let mut rng = TestRng::new(); + let protocol_version = ProtocolVersion::from_parts(2, 0, 0); + let value = NodeStatus { + protocol_version, + peers: Peers::random(&mut rng), + build_version: rng.random_string(5..10), + chainspec_name: "network-1".into(), + starting_state_root_hash: Digest::random(&mut rng), + last_added_block_info: None, + our_public_signing_key: None, + round_length: None, + next_upgrade: None, + uptime: TimeDiff::from_millis(0), + reactor_state: ReactorStateName::new(rng.random_string(5..10)), + last_progress: Timestamp::random(&mut rng), + available_block_range: AvailableBlockRange::random(&mut rng), + block_sync: BlockSynchronizerStatus::random(&mut rng), + latest_switch_block_hash: None, + }; + let response = BinaryResponse::from_value(value, protocol_version); + + // setup mock binary port with node status response + let port = get_port(); + let shutdown = Arc::new(tokio::sync::Notify::new()); + let request_id = Some(INITIAL_REQUEST_ID); + let _mock_server_handle = start_mock_binary_port_responding_with_given_response( + port, + request_id, + None, + Arc::clone(&shutdown), + response, + ) + .await; + + let mut config = NodeClientConfig::new_with_port_and_retries(port, 2); + config.network_name = Some("not-network-1".into()); + let res = FramedNodeClient::new(config).await; + + assert!(res.is_err()); + let error_message = res.err().unwrap().to_string(); + + assert_eq!(error_message, "Network name network-1 does't match name not-network-1 configured for node RPC connection"); + } + async fn query_global_state_for_string_value( rng: &mut TestRng, client: &FramedNodeClient, diff --git a/rpc_sidecar/src/testing/mod.rs b/rpc_sidecar/src/testing/mod.rs index 119a4a2c..cbbb47ec 100644 --- a/rpc_sidecar/src/testing/mod.rs +++ b/rpc_sidecar/src/testing/mod.rs @@ -103,6 +103,25 @@ pub async fn start_mock_binary_port_responding_with_stored_value( .await } +pub async fn start_mock_binary_port_responding_with_given_response( + port: u16, + request_id: Option, + number_of_responses: Option, + shutdown: Arc, + binary_response: BinaryResponse, +) -> JoinHandle<()> { + let request = get_dummy_request_payload(request_id); + let response = + BinaryResponseAndRequest::new(binary_response, &request, request_id.unwrap_or_default()); + start_mock_binary_port( + port, + response.to_bytes().unwrap(), + number_of_responses.unwrap_or(1), // Single response by default + shutdown, + ) + .await +} + pub async fn start_mock_binary_port( port: u16, data: Vec,