// file: crates/ksp-onchain-transport-lib/unit_tests/grpc_settings.rs // version: 3 fn endpoint(name: &str, enabled: bool, url: &str, session: crate::YellowstoneGrpcSessionSettings) -> crate::YellowstoneGrpcEndpointSettings { let parsed = crate::YellowstoneGrpcEndpointUrl::parse(url).expect("fixture Yellowstone gRPC URL must parse"); return crate::YellowstoneGrpcEndpointSettings::new( name, enabled, crate::YellowstoneGrpcProviderName::new("fixture"), crate::YellowstoneGrpcClusterName::new("devnet"), parsed, session, ); } #[test] fn grpc_endpoint_url_accepts_http_and_https_and_redacts_debug() { for value in ["http://127.0.0.1:10000", "https://yellowstone.example.invalid:443/path?token=GRPC-SECRET-CANARY"] { let parsed = crate::YellowstoneGrpcEndpointUrl::parse(value); assert!(parsed.is_ok()); let parsed = match parsed { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => continue, }; assert_eq!(parsed.as_str(), value); let rendered = format!("{parsed:?}"); assert_eq!(rendered, "YellowstoneGrpcEndpointUrl()"); assert!(!rendered.contains("GRPC-SECRET-CANARY")); } } #[test] fn grpc_endpoint_url_rejects_non_http_schemes_without_echoing_secret() { let result = crate::YellowstoneGrpcEndpointUrl::parse("wss://GRPC-SECRET-CANARY@example.invalid/socket"); assert!(result.is_err()); let error = match result { std::result::Result::Ok(_) => return, std::result::Result::Err(error) => error, }; let rendered = error.to_string(); assert!(!rendered.contains("GRPC-SECRET-CANARY")); assert!(!format!("{error:?}").contains("GRPC-SECRET-CANARY")); } #[test] fn grpc_endpoint_url_rejects_excessive_length_without_echoing_payload() { let value = format!("https://example.invalid/{}", "S".repeat(super::MAX_GRPC_ENDPOINT_URL_LENGTH_BYTES + 1)); let result = crate::YellowstoneGrpcEndpointUrl::parse(value); assert!(result.is_err()); let error = match result { std::result::Result::Ok(_) => return, std::result::Result::Err(error) => error, }; assert!(!format!("{error:?}").contains(&"S".repeat(64))); } #[test] fn grpc_session_defaults_are_bounded_and_validate() { let settings = crate::YellowstoneGrpcSessionSettings::default(); assert!(settings.validate().is_ok()); assert!(!settings.connect_timeout().is_zero()); assert!(!settings.unary_timeout().is_zero()); assert!(!settings.close_timeout().is_zero()); assert!(settings.request_channel_capacity() > 0); assert!(settings.update_channel_capacity() > 0); assert!(settings.max_inbound_message_size_bytes() > 0); assert!(settings.max_outbound_message_size_bytes() > 0); assert!(settings.reconnect().max_retries() <= super::MAX_GRPC_RECONNECT_RETRIES); } #[test] fn grpc_session_rejects_zero_excessive_and_reversed_runtime_bounds() { let zero = crate::YellowstoneGrpcSessionSettings::new( std::time::Duration::ZERO, std::time::Duration::from_secs(1), std::time::Duration::from_secs(1), crate::YellowstoneGrpcReconnectSettings::default(), 1, 1, 1, 1, ); assert!(zero.validate().is_err()); let excessive = crate::YellowstoneGrpcSessionSettings::new( super::MAX_GRPC_RUNTIME_DURATION + std::time::Duration::from_secs(1), std::time::Duration::from_secs(1), std::time::Duration::from_secs(1), crate::YellowstoneGrpcReconnectSettings::new( super::MAX_GRPC_RECONNECT_RETRIES + 1, std::time::Duration::from_millis(1), std::time::Duration::from_millis(2), ), super::MAX_GRPC_CHANNEL_CAPACITY + 1, 1, super::MAX_GRPC_MESSAGE_SIZE_BYTES + 1, 1, ); assert!(excessive.validate().is_err()); let reversed = crate::YellowstoneGrpcSessionSettings::new( std::time::Duration::from_secs(1), std::time::Duration::from_secs(1), std::time::Duration::from_secs(1), crate::YellowstoneGrpcReconnectSettings::new(5, std::time::Duration::from_secs(2), std::time::Duration::from_secs(1)), 1, 1, 1, 1, ); assert!(reversed.validate().is_err()); } #[test] fn grpc_transport_settings_validate_unique_enabled_endpoints_and_redact_urls() { let first = endpoint("first", true, "https://GRPC-SECRET-CANARY@example.invalid:443", crate::YellowstoneGrpcSessionSettings::default()); let second = endpoint("second", false, "http://127.0.0.1:10000", crate::YellowstoneGrpcSessionSettings::default()); let settings = crate::YellowstoneGrpcTransportSettings::new(std::vec![first.clone(), second]); assert!(settings.validate().is_ok()); let rendered = format!("{settings:?}"); assert!(!rendered.contains("GRPC-SECRET-CANARY")); assert!(!rendered.contains("example.invalid")); let duplicate = crate::YellowstoneGrpcTransportSettings::new(std::vec![first.clone(), first]); assert!(duplicate.validate().is_err()); } #[test] fn grpc_transport_settings_reject_excessive_descriptor_and_endpoint_count() { let oversized_name = "n".repeat(super::MAX_GRPC_DESCRIPTOR_LENGTH_BYTES + 1); let oversized = endpoint(oversized_name.as_str(), true, "http://127.0.0.1:10000", crate::YellowstoneGrpcSessionSettings::default()); assert!(crate::YellowstoneGrpcTransportSettings::new(std::vec![oversized]).validate().is_err()); let parsed = crate::YellowstoneGrpcEndpointUrl::parse("http://127.0.0.1:10000").expect("fixture Yellowstone gRPC URL must parse"); let endpoints = (0..=super::MAX_GRPC_ENDPOINT_COUNT) .map(|index| { return crate::YellowstoneGrpcEndpointSettings::new( format!("endpoint-{index}"), true, crate::YellowstoneGrpcProviderName::new("fixture"), crate::YellowstoneGrpcClusterName::new("devnet"), parsed.clone(), crate::YellowstoneGrpcSessionSettings::default(), ); }) .collect(); assert!(crate::YellowstoneGrpcTransportSettings::new(endpoints).validate().is_err()); } #[test] fn grpc_transport_settings_require_one_enabled_endpoint() { let disabled = endpoint("disabled", false, "http://127.0.0.1:10000", crate::YellowstoneGrpcSessionSettings::default()); assert!(crate::YellowstoneGrpcTransportSettings::new(std::vec![disabled]).validate().is_err()); assert!(crate::YellowstoneGrpcTransportSettings::new(std::vec![]).validate().is_err()); } #[test] fn grpc_metadata_validates_ascii_bounds_sensitivity_and_redacted_debug() { let public = crate::YellowstoneGrpcMetadataEntry::public("x-ksp-public", "VISIBLE-CANARY").expect("public metadata must validate"); let secret = crate::YellowstoneGrpcMetadataEntry::secret("x-ksp-token", "GRPC-SECRET-CANARY").expect("secret metadata must validate"); assert_eq!(public.key(), "x-ksp-public"); assert!(!public.is_secret()); assert!(secret.is_secret()); let rendered = format!("{public:?} {secret:?}"); assert!(!rendered.contains("VISIBLE-CANARY")); assert!(!rendered.contains("GRPC-SECRET-CANARY")); let mut metadata = tonic::metadata::MetadataMap::new(); assert!(secret.append_to(&mut metadata).is_ok()); let appended = metadata.get("x-ksp-token").expect("secret metadata must be appended"); assert!(appended.is_sensitive()); } #[test] fn grpc_metadata_rejects_reserved_binary_uppercase_malformed_and_oversized_values() { assert!(crate::YellowstoneGrpcMetadataEntry::public("grpc-timeout", "1").is_err()); assert!(crate::YellowstoneGrpcMetadataEntry::public("x-ksp-bin", "1").is_err()); assert!(crate::YellowstoneGrpcMetadataEntry::public("X-KSP-UPPER", "1").is_err()); assert!(crate::YellowstoneGrpcMetadataEntry::public("x-ksp-bad", "line\nfeed").is_err()); assert!(crate::YellowstoneGrpcMetadataEntry::secret("x-ksp-large", "S".repeat(super::MAX_GRPC_METADATA_VALUE_LENGTH_BYTES + 1)).is_err()); } #[test] fn grpc_endpoint_metadata_count_is_bounded_and_url_tracks_tls_scheme() { let http = crate::YellowstoneGrpcEndpointUrl::parse("http://127.0.0.1:10000").expect("HTTP URL must parse"); let https = crate::YellowstoneGrpcEndpointUrl::parse("https://example.invalid:443").expect("HTTPS URL must parse"); assert!(!http.uses_tls()); assert!(https.uses_tls()); let metadata = (0..=super::MAX_GRPC_METADATA_ENTRY_COUNT) .map(|index| { return crate::YellowstoneGrpcMetadataEntry::public(format!("x-ksp-{index}"), "value").expect("generated metadata must be valid"); }) .collect(); let endpoint = crate::YellowstoneGrpcEndpointSettings::new( "metadata-bound", true, crate::YellowstoneGrpcProviderName::new("fixture"), crate::YellowstoneGrpcClusterName::new("devnet"), http, crate::YellowstoneGrpcSessionSettings::default(), ); assert!(endpoint.with_metadata(metadata).is_err()); }