v0.3.13-pre.006

This commit is contained in:
2026-09-10 16:05:52 +02:00
parent c711213dcc
commit f688325170
14 changed files with 1549 additions and 51 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
// version: 17
// version: 18
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
@@ -62,6 +62,54 @@ fn http_pool(cluster: &str, role_name: &str, request_kind: &str) -> std::option:
};
}
fn http_polling_pool_with_identity(
cluster: &str,
role_name: &str,
endpoint_name: &str,
provider: &str,
request_kinds: &[&str],
) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
let url = match ksp_onchain_transport_lib::HttpEndpointUrl::parse("https://fixture.invalid/poll?token=HTTP-POLL-SECRET-CANARY") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let role = ksp_onchain_transport_lib::HttpEndpointRoleSettings::new(
ksp_onchain_transport_lib::HttpRoleName::new(role_name),
true,
request_kinds.iter().map(|value| return ksp_onchain_transport_lib::HttpRequestKind::new(*value)).collect(),
10,
ksp_onchain_transport_lib::HttpRoleLimits::new(
std::option::Option::None,
std::option::Option::None,
std::option::Option::None,
std::option::Option::None,
),
);
let endpoint = ksp_onchain_transport_lib::HttpEndpointSettings::new(
endpoint_name,
true,
ksp_onchain_transport_lib::HttpProviderName::new(provider),
ksp_onchain_transport_lib::HttpClusterName::new(cluster),
url,
std::time::Duration::from_secs(1),
std::time::Duration::from_secs(2),
std::option::Option::Some(4),
std::vec![role],
);
let settings = ksp_onchain_transport_lib::HttpTransportSettings::new(
std::vec![endpoint],
ksp_onchain_transport_lib::HttpRetrySettings::new(1, std::time::Duration::from_millis(10), std::time::Duration::from_millis(20)),
);
return match ksp_onchain_transport_lib::HttpTransportPool::new(settings) {
std::result::Result::Ok(value) => std::option::Option::Some(value),
std::result::Result::Err(_) => std::option::Option::None,
};
}
fn http_polling_pool(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
return http_polling_pool_with_identity(cluster, "live-poll", "poll-fixture", "fixture-provider", &["get_block", "get_blocks_with_limit", "get_slot"]);
}
fn ws_endpoint(
cluster: &str,
endpoint_name: &str,
@@ -2670,3 +2718,183 @@ async fn pre_009_abort_joins_in_flight_hydration_and_clears_pending_projection()
assert_eq!(cleaned.processing_frontier_slot(), std::option::Option::None);
return;
}
#[test]
fn v0_3_13_pre_006_http_block_polling_source_validates_bounds_capabilities_and_logical_identity() {
let pool = match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let source = match crate::RawTransactionIngestHttpBlockPollingSource::new(
pool.clone(),
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let same_identity_different_timing = match crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
pool,
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
std::time::Duration::from_secs(2),
256,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(source.source_key, same_identity_different_timing.source_key);
assert_eq!(source.network.as_str(), "devnet");
assert_eq!(source.poll_interval, crate::DEFAULT_RAW_TRANSACTION_INGEST_HTTP_POLL_INTERVAL);
assert_eq!(source.max_discovered_blocks_per_cycle, crate::DEFAULT_RAW_TRANSACTION_INGEST_HTTP_POLL_MAX_BLOCKS_PER_CYCLE);
let different_endpoint_pool = match http_polling_pool_with_identity(
"devnet",
"live-poll",
"poll-fixture-other",
"fixture-provider",
&["get_block", "get_blocks_with_limit", "get_slot"],
) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let different_endpoint = match crate::RawTransactionIngestHttpBlockPollingSource::new(
different_endpoint_pool,
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_ne!(source.source_key, different_endpoint.source_key);
let processed = crate::RawTransactionIngestHttpBlockPollingSource::new(
match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
},
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Processed,
);
assert!(processed.is_err());
let too_fast = crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
},
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
std::time::Duration::from_millis(99),
128,
);
assert!(too_fast.is_err());
let too_slow = crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
},
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
std::time::Duration::from_millis(30_001),
128,
);
assert!(too_slow.is_err());
for invalid_limit in [0_u16, 1025_u16] {
let invalid = crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
},
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
std::time::Duration::from_secs(1),
invalid_limit,
);
assert!(invalid.is_err());
}
let missing_capability_pool = match http_polling_pool_with_identity("devnet", "live-poll", "poll-missing", "fixture-provider", &["get_block", "get_slot"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let missing_capability = crate::RawTransactionIngestHttpBlockPollingSource::new(
missing_capability_pool,
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
);
assert!(missing_capability.is_err());
let debug = std::format!("{source:?}");
assert!(!debug.contains("HTTP-POLL-SECRET-CANARY"));
assert!(!debug.contains("fixture.invalid"));
return;
}
#[test]
fn v0_3_13_pre_006_http_block_polling_discovery_never_moves_before_run_frontier_and_requires_strict_order() {
assert!(super::validate_http_block_polling_discovery(100, &[]).is_ok());
assert!(super::validate_http_block_polling_discovery(100, &[100, 102, 105]).is_ok());
assert!(super::validate_http_block_polling_discovery(100, &[99]).is_err());
assert!(super::validate_http_block_polling_discovery(100, &[100, 100]).is_err());
assert!(super::validate_http_block_polling_discovery(100, &[102, 101]).is_err());
return;
}
#[test]
fn v0_3_13_pre_006_http_block_polling_qualifies_legacy_v0_v1_and_rejects_ambiguous_or_future_versions() {
let cases = [
(ksp_onchain_transport_lib::SolanaTransactionVersion::Legacy, ksp_raw_transaction_lib::RawTransactionVersion::Legacy),
(ksp_onchain_transport_lib::SolanaTransactionVersion::Number(0), ksp_raw_transaction_lib::RawTransactionVersion::Number(0)),
(ksp_onchain_transport_lib::SolanaTransactionVersion::Number(1), ksp_raw_transaction_lib::RawTransactionVersion::Number(1)),
];
for (wire, expected) in cases {
let qualified = super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Value(wire));
let qualified = match qualified {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let qualified = match qualified {
ksp_raw_transaction_lib::RawTransactionWireField::Value(value) => value,
_ => return,
};
assert_eq!(qualified, expected);
}
assert!(
super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Value(
ksp_onchain_transport_lib::SolanaTransactionVersion::Number(2),
))
.is_err()
);
assert!(super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Omitted).is_err());
assert!(super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Null).is_err());
return;
}
#[test]
fn v0_3_13_pre_006_runtime_resources_reject_duplicate_http_polling_identity_even_when_timing_differs() {
let first = match crate::RawTransactionIngestHttpBlockPollingSource::new(
match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
},
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let duplicate = match crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
match http_polling_pool("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
},
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
std::time::Duration::from_secs(2),
256,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let mut resources = crate::RawTransactionIngestRuntimeResources::from_http_block_polling_source(first);
let pushed = resources.try_push_http_block_polling_source(duplicate);
assert!(pushed.is_err());
assert_eq!(resources.source_count(), 1);
return;
}